[英]Is there a way to model an optional many-to-many relationship in Entity Framework?
实体框架中是否有一种方法(我假设它将使用流畅的语法,因为数据注释有些限制)来建模多对多关系,其中双方都是可选的(0..M到0..N)关系)? 用例是这样的:我想允许用户向实体添加标签。 标签到实体是M:N关系,但两者都不是必需的。 也就是说,可以存在不应用于任何实体的标签,并且实体可以是未标记的。 这对我来说似乎相当合理。 我不能简单地使用以下模型:
public virtual ICollection<Tag> Tags { get; set; }
和
public virtual ICollection<Entity> Entities { get; set; }
因为每个类都有其他关系,并且我得到“外键约束可能导致循环或多个级联路径”。 我希望也许我可以这样做:
modelBuilder.Entity<Tag>().HasOptional(t => t.Entities);
modelBuilder.Entity<Entity>().HasOptional(t => t.Tags);
但我被警告称,EF“无法确定该协会的主要目标。” 从阅读来看,似乎这种关系必须有一个主要目的,但就我而言,这是不可取的。
我可以添加一个类来表示桥表并手动处理映射,但我宁愿不要混淆代码。 我想知道是否还有另一种方法可以在EF中对此进行建模。
要填写更多细节,还有一个Author类(相当于Users)。 作者和标签是1:M,作者与实体也是1:M。 当然,问题是实体类在级联树中出现两次。 使标记/实体关系可选将解决此问题。 我还可以修复它,如果有办法通过实体获得标签,但由于标签可以存在而不连接到实体,我认为这是不可能的。
以下是相关代码的摘要:
public class Author
{
public Guid Id { get; set; }
public virtual List<Entity> Entities { get; set; }
public virtual List<Tag> Tags { get; set; }
}
public class Tag
{
public Guid Id { get; set; }
public Guid AuthorId { get; set; }
public virtual Author Author { get; set; }
public virtual ICollection<Entity> Entities { get; set; }
}
public class Entity
{
public Guid Id { get; set; }
public Guid AuthorId { get; set; }
public virtual Author Author { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
编辑:
使用.HasMany().WithMany()
下面建议的.HasMany().WithMany()
给我这个:
CREATE TABLE [dbo].[TagEntities] (
[Tag_Id] [uniqueidentifier] NOT NULL,
[Entity_Id] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_dbo.TagEntities] PRIMARY KEY ([Tag_Id], [Entity_Id])
)
但我想要的是Tag_Id和Entity_Id在这个表上可以为空。 也许这个模型没有像我想的那么有意义? 你能有一个双面都可以为空的桥牌桌吗?
使用
modelBuilder.Entity<Tag>().HasMany(t => t.Entities)
.WithMany(t => t.Tags);
代替
modelBuilder.Entity<Tag>().HasOptional(t => t.Entities);
modelBuilder.Entity<Entity>().HasOptional(t => t.Tags);
我不知道这是否是正确的答案,但我通过创建一个名为DbEntity的基类来解决这个问题,其他类继承自该类。 所以现在作者刚才:
// Both entities and tags are part of this collection
public virtual List<DbEntity> Entities { get; set; }
“实体”(在我的代码中具有特殊含义)和“标签”都是DbEntity的子类。 这消除了多个级联路径,同时保留了导航属性,但我确实需要这样做:
author.Entities.OfType<Tag>();
要么
author.Entities.OfType<Entity>();
获取特定的实体集。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.