实体框架代码在使用接口时首先生成奇怪的数据库架构



>我有以下类和接口。

 public interface ITaggable
    {
         ICollection<Tag> Tags { get; set; }
    }
 public class Book :ITaggable
    {
        [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
        public Guid BookId { get;set; }
        public string Title { get; set; }
        public string Author { get; set; }
        public virtual ICollection<Tag> Tags {get; set;}
    }
public class Pen:ITaggable
    {
        [DatabaseGenerated(DatabaseGenerationOption.Identity)]
        public Guid PenId { get; set; }
        public string Color { get; set; }
        public virtual ICollection<Tag> Tags {get; set;}
    }
public class Tag
    {
        [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
        public Guid TagId { get; set; }
        public string Name { get; set; }
        public virtual ICollection<ITaggable> Items { get; set; }
    }

对于上述模型,它生成下表结构

书 -->书号 , 书名 , 作者

笔 -->笔 , 颜色

标记 -->标签ID , 名称 ,书本ID , 笔笔ID

当我插入以下数据时

            Tag tag = new Tag();
            tag.Name = "Stationary";
            Book b1 = new Book();
            b1.Title = "Head first c#";
            b1.Author = "Betty";
            b1.Tags = new List<Tag>() { tag };
            Book b2 = new Book();
            b2.Title = "Head first Java";
            b2.Author = "Katty";
            b2.Tags = new List<Tag>() { tag };
            Pen p = new Pen();
            p.Color = "Red";
            p.Tags = new List<Tag>() { tag };
            context.Books.Add(b1);
            context.Books.Add(b2);
            context.Pens.Add(p);
            context.SaveChanges();

它不会插入第二本书的标签数据

我想实现的是我想实现一个三表标记系统这里显示坚持我的类结构

是的,它不会存储其中一本书的标签信息,因为您的标签实例只能与单本书相关联。这需要你在BookTag之间建立多对多的关系,但你的关系是一对多的。PenTag之间的关系也是一对多。这可以通过表中Tag外键清晰可见。

问题是 EF 代码首先跳过ICollection<ITaggable> Items - 代码优先不适用于接口。您必须将标签定义为:

public class Tag
{
    [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
    public Guid TagId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Book> Books { get; set; }
    public virtual ICollection<Pen> Pens { get; set; }
}

这将映射 BookTag 之间的多对多以及 PenTag 之间的多对多。如果还想要收集ITaggable,则可以公开另一个连接BooksPens的属性。

如果你真的想要一对多的关系,那么你不能指望标签会与多本书相关联,在这种情况下,你的Tag实体应该看起来像:

public class Tag
{
    [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
    public Guid TagId { get; set; }
    public string Name { get; set; }
    public virtual Book Book { get; set; }
    public virtual Pen Pen { get; set; }
}

同样,您可以将Items创建为计算属性。从这些例子中可以明显看出任何关系的组合。

编辑:

如果不想在标记中公开导航属性,则必须使用流畅的 api:

public class Context : DbContext
{
    public DbSet<Book> Books { get; set; }
    public DbSet<Pen> Pens { get; set; }
    public DbSet<Tag> Tags { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Book>()
                    .HasMany(b => b.Tags)
                    .WithMany();
        modelBuilder.Entity<Pen>()
                    .HasMany(p => p.Tags)
                    .WithMany();
    }
}

可以在团队博客上找到更多流畅 ADO.NET API 参考,但它不符合数据(适用于 CTP5)。

相关内容

  • 没有找到相关文章

最新更新