C# 如何在EF中保存关系项

C# 如何在EF中保存关系项,c#,sql,entity-framework,C#,Sql,Entity Framework,我的数据库中有3个表 1个称为图像,1个称为标记,最后一个表称为ImageTagID “我的图像”表具有ID和路径 我的标签有ID和短语 我的ImageTagID有ID、ImageId和TagId 我希望这些名称有助于自我解释,但Image表和ImageTagID之间存在1对多关系,其中Image.ID连接到ImageTagID.ImageId 标记表和ImageTagID之间有一种1对1的关系,其中Tag.Id连接到ImageTagID.Id 我在SSMS中添加了一个数据库图,并创建了所有键和

我的数据库中有3个表

1个称为图像,1个称为标记,最后一个表称为ImageTagID

“我的图像”表具有ID和路径

我的标签有ID和短语

我的ImageTagID有ID、ImageId和TagId

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

标记表和ImageTagID之间有一种1对1的关系,其中Tag.Id连接到ImageTagID.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();
    }
private Dal.MyEntities\u dc=new MyEntities();
公共void保存(字符串文件路径、IList标记)
{
FileInfo fi=新的FileInfo(filePath);
此._dc.Images.Add(新图像()
{
Path=fi.DirectoryName
});
foreach(标签中的var标签)
{
此._dc.Tags.Add(新标记()
{
短语=标记
});
}
_dc.SaveChanges();
}
上述内容保存到标记表和图像表中,但ImageTagIds表仍为空。我知道为什么,我从来没有试图写信给它,但这就是我迷失的地方。我不知道我可以在ImageTagsId表中写入/编码什么


更多的研究让我发现,这表明(我认为)EF应该知道这些关系在哪里。即使是这样,我也不知道我可以保存什么/如何保存,因为当我向数据库中添加新条目时,我不知道ID将是什么。

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

试试下面的方法

_Add(new Tag(){Phrase=“something”})

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

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

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

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

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

前提是您的
ImagetTagId
具有以下内容:

  • 关系,指向
    图像的导航属性
  • 一个关系,以及指向
    标记的导航属性
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,因为在保存ID之前,ID不可用。这样就需要将导航属性设置为
Tag
Image

调用
SaveChanges
时,图像将保存到数据库中,并获取其数据库生成的id。保存每个标记时也会发生同样的情况。保存每个
ImageTagId
时,由于它与已具有id的标记和图像相关,请复制这些id,并保存“修复”对象。请阅读MSDN:,特别注意同步FKs和导航属性之间更改的部分

EF中的多对多关系

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

  • 多对多侧面中的一方的FK
  • 另一边的FK
  • 由两个FK组成的PK
在您的特定情况下,您应该有一个表,其中只有一个Id是FK to Image,另一个Id是FK to Tag,以及一个由两个FK组成的主键

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


如果您执行多对多这样的操作,连接表条目将由EF自动管理。

您可以发布EF生成的类吗?我希望标记具有图像集合,图像具有标记集合-您只需创建一个新项并将另一个项添加到集合中。ImageTagId是否具有标记和图像属性?如果有,您可以创建一个新的ImageTagId并分配一个新标记和一个新图像。我的图像没有给我Tags属性,只有ImageTagId属性可用。ImagesTagsIds表中除了两个表的ID之外还有其他列吗?是的,这是正确的。在我的ImageTagId中,我有两个新属性,一个called图像和其他标签。但它们不是集合,我只能访问属性。不确定你在谈论哪些规则