如何在EF中保存关系条目

时间:2014-07-08 06:50:26

标签: c# sql entity-framework

我的数据库中有3个表。

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

我的图片表有ID和路径

我的标签有ID和短语

我的ImageTagIds有ID,ImageId和TagId

我希望这些名称有助于自我解释,但Image表和ImageTagIds之间存在1对多的关系,其中Image.ID连接到ImageTagIds.ImageId

Tag表与ImageTagIds之间存在1对人的关系,其中Tag.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将会是什么。

2 个答案:

答案 0 :(得分:1)

您正在添加标签,但您正在添加图片,但您没有为图片添加标签。

尝试以下

  

_dc.Images.FirstOrDefault()。Tags.Add(new Tag(){Phrase =&#34; something&#34;});

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

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

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

通常,您缺少图像中Tags属性的原因是您的表中除了TagId和ImageId之外还有更多列,因此EF会创建3个类来表示您的表而不是2个。

答案 1 :(得分:1)

这是一个多对多关系,使用具有附加属性的联结表实现(并且密钥的定义与EF对多对多关系的预期不匹配)。在这种情况下,EF将联结表视为任何其他实体,因此您必须自己创建并将条目保存到此表。 请参阅底部的多对多EF关系的说明

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

  • 关系,Image
  • 的导航属性
  • 关系和导航属性Tag

并且ID是数据库生成的(标识),然后您只需创建所有必需的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时,图像将保存到数据库,并获取其数据库生成的ID。保存每个标签时也会发生同样的情况并且,在保存每个ImageTagId时,因为它与标签和已有ID的图像相关,EF复制这些ID,并将“修复”对象保存到DB。在MSDN上阅读此内容:Relationships and Navigation Properties,特别注意同步FK和导航属性之间的更改部分。

EF中的多对多关系

如果要在EF上定义纯多对多关系,则需要只有

的联结表
  • 一个FK到众多方面之一
  • 一个FK到另一边
  • 由两个FK组成的PK

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

当您使用EF多对多关系时,联结表在模型中不会显示为entiy。相反,您只有从每一侧到另一侧的集合的导航属性。在您的特定方面,您在Tag上有一个Images集合,在Image上有一个Tags集合。

如果像这样阻止多对多,联结表条目将由EF自动管理。