遵循您的表格结构有点困难,因此我尝试使用一些任何人都应该能够遵循的常见实体来设置一个全面的示例。如果这不能完全描述您的问题,请发表评论。
注意我故意使用了非常糟糕的外键来确保实体框架中的帮助自动映射对我没有帮助,并表明这适用于您可能拥有的任何遗留数据库设计。
首先是示例中的预期结构
- 一个
Company 拥有许多Articles 和许多Invoices。
- 一个
Invoice 拥有多个InvoiceRows。
- 每个
InvoiceRow 都可以选择引用Article。
实际的实体
class Company
{
public int TheCompanyKey { get; set; }
public virtual ICollection<Invoice> Its_Invoices { get; set; }
public virtual ICollection<Article> Its_Articles { get; set; }
}
class Invoice
{
public int Its_CompanyKey { get; set; }
public int TheInvoiceKey { get; set; }
public string InvoiceNumber { get; set; }
public DateTime InvoiceDate { get; set; }
public virtual Company Its_Company { get; set; }
public virtual ICollection<InvoiceRow> Its_Rows { get; set; }
}
class InvoiceRow
{
public int Rows_Company_Key { get; set; }
public int Its_InvoiceID { get; set; }
public int RowNumber { get; set; }
public int? Its_Articles_ID { get; set; }
public string Text { get; set; }
public double Price { get; set; }
public virtual Invoice Its_Invoice { get; set; }
public virtual Article Its_Article { get; set; }
}
class Article
{
public int TheArticleCompany_Key { get; set; }
public int TheArticleKey { get; set; }
public string ArticleNumber { get; set; }
public double Cost { get; set; }
public double TargetPrice { get; set; }
public virtual Company Its_Company { get; set; }
}
带有 OnModelCreating() 的 DbContext
有多种方法可以生成所需的结构,具体取决于您认为是自上而下还是自下而上。我对建模的看法是从基表开始,然后描述孩子与它们的关系。
class MyContext : DbContext
{
public MyContext() : base("name=MyContext")
{
}
public virtual IDbSet<Company> Companies { get; set; }
public virtual IDbSet<Invoice> Invoices { get; set; }
public virtual IDbSet<InvoiceRow> InvoiceRows { get; set;}
public virtual IDbSet<Article> Articles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Company>()
.HasKey(e => e.TheCompanyKey);
modelBuilder.Entity<Article>()
.HasKey(e => new { e.TheArticleCompany_Key, e.TheArticleKey })
.HasRequired(e => e.Its_Company).WithMany(e => e.Its_Articles).HasForeignKey(e => e.TheArticleCompany_Key);
modelBuilder.Entity<Invoice>()
.HasKey(e => new { e.Its_CompanyKey, e.TheInvoiceKey })
.HasRequired(e => e.Its_Company).WithMany(e => e.Its_Invoices).HasForeignKey(e => e.Its_CompanyKey);
modelBuilder.Entity<InvoiceRow>()
.HasKey(e => new { e.Rows_Company_Key, e.Its_InvoiceID, e.RowNumber });
modelBuilder.Entity<InvoiceRow>()
.HasRequired(e => e.Its_Invoice).WithMany(e => e.Its_Rows)
.HasForeignKey(e => new { e.Rows_Company_Key, e.Its_InvoiceID }).WillCascadeOnDelete();
modelBuilder.Entity<InvoiceRow>()
.HasOptional(e => e.Its_Article)
.WithMany()
.HasForeignKey(e => new { e.Rows_Company_Key, e.Its_Articles_ID });
}
}
终于生成的迁移
在Package Manager Console 窗口中运行add-migration multikeys 会导致以下迁移:
public partial class multikeys : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Articles",
c => new
{
TheArticleCompany_Key = c.Int(nullable: false),
TheArticleKey = c.Int(nullable: false),
ArticleNumber = c.String(),
Cost = c.Double(nullable: false),
TargetPrice = c.Double(nullable: false),
})
.PrimaryKey(t => new { t.TheArticleCompany_Key, t.TheArticleKey })
.ForeignKey("dbo.Companies", t => t.TheArticleCompany_Key, cascadeDelete: true)
.Index(t => t.TheArticleCompany_Key);
CreateTable(
"dbo.Companies",
c => new
{
TheCompanyKey = c.Int(nullable: false, identity: true),
})
.PrimaryKey(t => t.TheCompanyKey);
CreateTable(
"dbo.Invoices",
c => new
{
Its_CompanyKey = c.Int(nullable: false),
TheInvoiceKey = c.Int(nullable: false),
InvoiceNumber = c.String(),
InvoiceDate = c.DateTime(nullable: false),
})
.PrimaryKey(t => new { t.Its_CompanyKey, t.TheInvoiceKey })
.ForeignKey("dbo.Companies", t => t.Its_CompanyKey, cascadeDelete: true)
.Index(t => t.Its_CompanyKey);
CreateTable(
"dbo.InvoiceRows",
c => new
{
Rows_Company_Key = c.Int(nullable: false),
Its_InvoiceID = c.Int(nullable: false),
RowNumber = c.Int(nullable: false),
Its_Articles_ID = c.Int(),
Text = c.String(),
Price = c.Double(nullable: false),
})
.PrimaryKey(t => new { t.Rows_Company_Key, t.Its_InvoiceID, t.RowNumber })
.ForeignKey("dbo.Articles", t => new { t.Rows_Company_Key, t.Its_Articles_ID })
.ForeignKey("dbo.Invoices", t => new { t.Rows_Company_Key, t.Its_InvoiceID }, cascadeDelete: true)
.Index(t => new { t.Rows_Company_Key, t.Its_Articles_ID })
.Index(t => new { t.Rows_Company_Key, t.Its_InvoiceID });
}
public override void Down()
{
DropForeignKey("dbo.Articles", "TheArticleCompany_Key", "dbo.Companies");
DropForeignKey("dbo.InvoiceRows", new[] { "Rows_Company_Key", "Its_InvoiceID" }, "dbo.Invoices");
DropForeignKey("dbo.InvoiceRows", new[] { "Rows_Company_Key", "Its_Articles_ID" }, "dbo.Articles");
DropForeignKey("dbo.Invoices", "Its_CompanyKey", "dbo.Companies");
DropIndex("dbo.InvoiceRows", new[] { "Rows_Company_Key", "Its_InvoiceID" });
DropIndex("dbo.InvoiceRows", new[] { "Rows_Company_Key", "Its_Articles_ID" });
DropIndex("dbo.Invoices", new[] { "Its_CompanyKey" });
DropIndex("dbo.Articles", new[] { "TheArticleCompany_Key" });
DropTable("dbo.InvoiceRows");
DropTable("dbo.Invoices");
DropTable("dbo.Companies");
DropTable("dbo.Articles");
}
}
总结
我相信这描述了 OP 问题,并且通过一些研究可以很好地理解如何使用 Fluent 来映射实体。
祝你好运!