繁体   English   中英

同一列外键引用实体框架中的多个表

[英]Same column foreign key referencing multiple tables in Entity Framework

我有两个课

public class TypeA
{
    public Guid Id { get; set; }
    public List<Comment> Comments { get; set; }
}
public class TypeB
{
    public Guid Id { get; set; }
    public List<Comment> Comments { get; set; }
}

然后有

public class Comment
{
    public Guid Id { get; set; }
    public Guid ParentId { get; set; } //foreign key either to TypeA or TypeB
    public int Type { get; set; } //shows which class is referenced by foreign key ParentId
}

Comment具有TypeATypeB外键。 并且有一个属性Type ,它告诉您正在引用哪个外键。

现在我要做

_context.Set<TypeA>().Include(x => x.Comments).First(x => x.Id == Id)

但是可以限制Include语句或编写查询来检查Type属性以获取适当的外键引用,例如

_context.Set<TypeA>().Include(x => x.Comments.Where(c=>c.Type == 1)).First(x => x.Id == Id)

我想可以在对查询中的Comment进行分组时完成此操作,但是TypeATypeB具有许多属性,我想避免在select语句中编写new关键字来分配所有属性。

编辑:

我对自己现在拥有的一切感到非常满意。 我这样做是出于理智,以防万一TypeATypeB id属性是相同的(99.9999999不会)。

如果正确设置了实体映射,则无需在Include语句中过滤某些内容。

public class TypeA
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public virtual ICollection<Comment> Comments { get; set; } = new List<Comment>();
    public Comment AddComment(string text)
    {
        var comment = new Comment { Id = Guid.NewGuid(), ParentId = Id, Type = Types.TypeA, Text = text };
        Comments.Add(comment);
        return comment;
    }
}

public class TypeB
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public virtual ICollection<Comment> Comments { get; set; } = new List<Comment>();
    public Comment AddComment(string text)
    {
        var comment = new Comment { Id = Guid.NewGuid(), ParentId = Id, Type = Types.TypeB, Text = text };
        Comments.Add(comment);
        return comment;
    }
}

public enum Types
{
    TypeA = 0,
    TypeB = 1
}

public class Comment
{
    public Guid Id { get; set; }
    public Guid ParentId { get; set; }
    public Types Type { get; set; }
    public string Text { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<TypeA> TypeAs { get; set; }
    public DbSet<TypeB> TypeBs { get; set; }

    public MyContext() : base("Name=MyContext") { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<TypeA>()
            .HasKey(e => e.Id)
            .HasMany(e => e.Comments).WithMany();

        modelBuilder.Entity<TypeB>()
            .HasKey(e => e.Id)
            .HasMany(e => e.Comments).WithMany();
    }
}
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }
}

void Main()
{   
    // helper code to use migrations, just for demo purposes
    var migrator = new DbMigrator(new Configuration());
    migrator.Update();
    //

    var db = new MyContext();
    var a = new TypeA { Id = Guid.NewGuid() };
    db.TypeAs.Add(a);

    var b = new TypeB { Id = Guid.NewGuid() };
    db.TypeBs.Add(b);

    db.SaveChanges();

    a.AddComment("A1 ");
    a.AddComment("A2");

    b.AddComment("B1");
    b.AddComment("B2");
    b.AddComment("B3");

    db.SaveChanges();

    var dba = db.TypeAs.Include(x => x.Comments).First(e => e.Id == a.Id);
    foreach (var c in dba.Comments)
    {
        Console.WriteLine("{0} {1} {2} {3}", c.Text, c.Id, c.ParentId, c.Type.ToString());
    }
}

唯一的缺点是将涉及其他链接表(TypeAComment,TypeBComment)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM