如何在EF中保存关系条目

本文关键字:关系 保存 EF | 更新日期: 2023-09-27 18:11:49

我的数据库中有3个表。

1名为Images, 1名为Tags最后一个表名为ImageTagIds

My Images table有ID和Path

我的标签有ID和短语

和我的ImageTagIds有ID, ImageId和TagId

我希望这些名字有助于使这个自我解释,但有一个1到许多图像表和ImageTagIds之间的关系,其中图像。ID连接ImageTagIds。ImageId

标签表和ImageTagIds之间有一个1到1的关系,其中标签。Id连接ImageTagIds。Id

我在SSMS中添加了一个数据库图,并创建了所有的键和关系。

在VS 2012中,我创建了一个新的EF (.edmx)文件,并添加了我的表。VS做了一些巫术,我现在可以把我的桌子作为对象。这工作得很好,我可以查询和保存没有异常。

我的问题是如何建立关系。

这是我得到的长度

    private Dal.MyEntities _dc = new MyEntities();
    public void Save(string filePath, IList<string> tags)
    {
        FileInfo fi = new FileInfo(filePath);
        this._dc.Images.Add(new Image()
        {
            Path = fi.DirectoryName
        });
        foreach (var tag in tags)
        {
            this._dc.Tags.Add(new Tag()
            {
                Phrase = tag
            });
        }
        _dc.SaveChanges();
    }

上面的内容保存到Tags表和Image表中,但是ImageTagIds表仍然为空。我知道为什么,我从来没有试图给它写信,但这就是我迷失的地方。我不知道我可以写/代码到ImageTagsId表。

更多的研究引导我到http://www.entityframeworktutorial.net/entity-relationships.aspx,这说(我认为)EF应该知道关系在哪里。即使是这样,我也不知道我可以保存什么/如何保存,因为当我向数据库添加新条目时,我不知道ID将是什么。

如何在EF中保存关系条目

您正在添加标签,您正在添加图像,但您没有向图像添加标签。

试试下面的

.Tags

_dc.Images.FirstOrDefault()。Add(new Tag() {Phrase = "something"});

从实体的角度来看,这将为特定的图像添加一个标签。从db表的角度来看,它会将标签添加到Tags表和ImageTagIds表中。

EDIT:如果你没有Tags属性,你应该首先确保你的数据库关系是正确的。如果不是这样,您可以尝试

TagsImagesIds tagImageRelation = new TagsImagesIds();
tagImageRelation.ImageId = image.Id;
tagImage.Relation.TagId = tag.Id;
_dc.TagsImagesIds.Add(tagImageRelation);

通常你在图像中缺少Tags属性的原因是你有更多的列在你的表中,而不是TagId和ImageId,所以EF创建3个类来代表你的表,而不是2。

这是一个多对多关系,用一个具有附加属性的连接表实现(键的定义与EF期望的多对多关系不匹配)。在这种情况下,EF将连接表视为任何其他实体,因此您必须自己创建并保存该表的条目。参见底部关于多对多EF关系的说明

如果您的ImagetTagId具有以下内容:

  • 一个关系,一个指向Image的导航属性
  • 关系,以及Tag
  • 的导航属性

和ID是数据库生成的(identity),那么您只需创建所有必要的ImageTagId对象并设置导航属性。当您调用SaveChanges时,DbContext将进行关系修复,在ImageTagId对象中设置正确的id并将它们保存到数据库中。

应该是这样的:

    Image img = new Image()
    {
        Path = fi.DirectoryName
    };
    this._dc.Images.Add(img);
    foreach (var tag in tags)
    {
        Tag tag = new Tag()
        {
            Phrase = tag
        };
        this._dc.Tags.Add();
        ImageTagId = new ImageTagId { Image = image, Tag = tag };
        this._dc.ImageTagIds.Add(ImageTagId);
    }

显然你不能做的是在ImageTagId中设置id,因为它们在保存之前是不可用的。这就是为什么有必要为TagImage设置导航属性。

当您调用SaveChanges时,图像被保存到db中,并获得其db生成的id。保存每个标记时也会发生同样的情况。并且,当保存每个ImageTagId时,因为它与已经具有id的标签和图像相关,EF复制这些id,并将"固定"对象保存到DB。请在MSDN:关系和导航属性上阅读本文,特别注意一节同步fk和导航属性之间的更改。

EF中的多对多关系

如果你想在EF上定义一个纯多对多关系,你需要一个只有

的连接表
  • 一个FK到多对多面之一
  • 一个FK到另一边
  • 由两个FKs组成的PK

在您的特殊情况下,您应该有一个表,它只有一个Id是FK到Image,另一个Id是FK到Tag,以及一个由两个FK组成的主键。

当您使用EF多对多关系时,连接表在模型中不作为实体出现。相反,您只有从一侧到另一侧集合的导航属性。在您的特定侧,您将在标签上有一个图像集合,在图像上有一个标签集合。

如果像这样实现多对多,那么连接表项将由EF自动管理。