如何使用Entity Framework 7在代码中首先处理这两个模型?

时间:2015-03-03 17:03:11

标签: c# entity-framework asp.net-core jointable entity-framework-core

问题

我正在编写将模拟库的概念ASP.NET 5 MVC6的证明。我正在使用CTP6和beta3。

如何使用代码优先方法在Entity Framework 7中定义它们的关系?

Shelf and Books需要一个连接表。在我看来,这个应用程序将一次考虑一个架子和自己的书籍。换句话说,一个书架与书籍有一对多的关系。

模型

货架型号:

public class Shelf
{
    public int ShelfId { get; set; }

    public string ShelfName { get; set; }

    public ShelfType MyProperty { get; set; }

    public virtual List<Book> Books { get; set; }

    public DateTime Created { get; set; }

    public string CreatedBy { get; set; }

    public DateTime Updated { get; set; }

    public string UpdatedBy { get; set; }

}

图书模型:

public class Book
{
    public int BookId { get; set; }

    public string BookName { get; set; }

    public string BookAuthor { get; set; }

    public string BookGenre { get; set; }

    public DateTime BookPublishedDate { get; set; }

    public string Description { get; set; }

    public DateTime Created { get; set; }

    public string CreatedBy { get; set; }

    public DateTime Updated { get; set; }

    public string UpdatedBy { get; set; }

}

目标

我想在ASP.NET 5中实现类似this的内容。由于TPH和其他功能尚未在EF7中实现,我是否走上正轨?

换句话说,我在想以下几点:

  • ShelfBookViewModel(毕竟我需要一个视图模型来显示书架和书籍,或书籍并能够回到书架上)。我可能只会将它命名为ShelfBook。这似乎是错误的做法。
  • 我更希望EF7能够弄清楚我有一个连接并为不同的关注点创建视图模型。否则,这违反了SOLID代码的做法。下面给出的东西(来自之前的链接)。
  • 尚未在EF7中实现加入表格,我要求徒劳无功?

我无法让以下工作如下所示:

 modelBuilder.Entity<Shelf>() 
            .HasMany(p => p.Shelfs) 
            .WithMany(t => t.Books) 
            .Map(mc => 
               { 
                   mc.ToTable("ShelfJoinBook"); 
                   mc.MapLeftKey("ShelfId"); 
                   mc.MapRightKey("BookId"); 
               });

感谢您抽出宝贵时间阅读我的问题。我希望其他人觉得这很有用。

2 个答案:

答案 0 :(得分:3)

要回答有关多对多的问题,您应该按如下方式定义映射(并且必须更新模型类):

modelBuilder.Entity<Shelf>() 
    .HasMany(p => p.Books) 
    .WithMany(t => t.Shelves) // doesn't exist 
    .Map(mc => 
       { 
           mc.ToTable("BookShelves"); 
           mc.MapLeftKey("ShelfId"); 
           mc.MapRightKey("BookId"); 
       });

要求您向ICollection<Shelf> Shelves { get; set; }添加Book。但是,如果您这样做,那么您将拥有以下内容(这是您的示例的MCVE版本):

public class Shelf
{
    public int ShelfId { get; set; }
    public virtual ICollection<Book> Books { get; set; }
}

public class Book
{
    public int BookId { get; set; }
    public virtual ICollection<Shelf> Shelves { get; set; }
}

然后您不再需要映射,因为EF会按惯例为您生成所有关系,包括仅在数据库本身中可见的连接表。

然而 - 从您的实际模型类和围绕它们的讨论 - 看起来您真的只需要一对多,在这种情况下,您应该接受Pynt的答案,并忽略我的。

修改

正如Gert Arnold在评论中指出的那样,EF7目前(不再是?)支持生成的连接表,这意味着我们必须推出自己的连接表,probably better anyway

这里有一种方式,我想我可以从现在开始做我自己的简单连接表,如果EF不再为我做这些(警告 - 我只是试图关闭这个循环问题...我不打算在编译器中尝试这个,所以YMMV):

public class Shelf
{
    public int ShelfId { get; set; }
    public virtual ICollection<BookShelf> BookShelves { get; set; }
    public virtual IQueryable<Book> Books
    {
        get
        {
            return BookShelves.Where(s => s.ShelfId == ShelfId)
                              .Select(s => s.Book);
        }
    }
}

public class Book
{
    public int BookId { get; set; }
    public virtual ICollection<BookShelf> BookShelves { get; set; }
    public virtual IQueryable<Shelf> Shelves
    {
        get
        {
            return BookShelves.Where(s => s.BookId == BookId)
                              .Select(s => s.Shelf);
        }
    }
}

public class BookShelf
{
    [Key]
    public int BookId { get; set; }
    [ForeignKey("BookId")]
    public Book Book { get; set; }
    [Key]
    public int ShelfId { get; set; }
    [ForeignKey("ShelfId")]
    public Shelf Shelf { get; set; }
}

答案 1 :(得分:1)

我处理类似的情况,虽然它可能不符合您的需求。我使用数据注释,因为我没有费心去学习如何通过lambda映射设置外键。通过以下设置,您可以为每个书架设置一个书籍实例,并且书架可以包含许多书籍。我已将关系属性移动到类的底部以便于可视化。

货架型号:

public class Shelf
{
    public int ShelfId { get; set; }

    public string ShelfName { get; set; }

    public ShelfType MyProperty { get; set; }

    public DateTime Created { get; set; }

    public string CreatedBy { get; set; }

    public DateTime Updated { get; set; }

    public string UpdatedBy { get; set; }

    public virtual ICollection<Book> Books { get; set; }
}

书籍型号:

using System.ComponentModel.DataAnnotations.Schema;
public class Book
{
    public int BookId { get; set; }

    public string BookName { get; set; }

    public string BookAuthor { get; set; }

    public string BookGenre { get; set; }

    public DateTime BookPublishedDate { get; set; }

    public string Description { get; set; }

    public DateTime Created { get; set; }

    public string CreatedBy { get; set; }

    public DateTime Updated { get; set; }

    public string UpdatedBy { get; set; }

    public int ShelfId { get; set; }
    [ForeignKey("ShelfId")]
    public Shelf Shelf { get; set; }
}