它有点难以遵循你的表格结构,所以我试图设置一个全面的例子,使用任何人都应该能够遵循的共同实体。请评论,如果这不能完全描述你的问题。
注意,我已经故意使用非常低劣的外键,以确保在实体框架的帮助自动映射并不能帮助我,并表明这适用于任何传统的数据库设计你可能有。
首先在示例
- 一个
Company
预期结构拥有许多Article
S和许多Invoice
秒。
- 其中一个
Invoice
持有许多InvoiceRow
s。
- 每个
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如何用于映射实体。
祝你好运!
谢谢你的帮助。最后我注意到这个问题发生了,因为我有两个不同的流利API文件,我正在修改不正确的文件。在注意到这一点之后,我能够正确配置外键,并且您的示例也得到了帮助。 – Anton