Entity Framework 数据库映射关系(使用Seed()方法重复创建)
Entity Framework database mapping relationships (Duplicate creation using Seed() method)
我用 and 创建了一个 post。
这些可以作为参考,但我认为它们已处理。
我因这些问题而产生的问题以及我(需要或不需要)采取的行动让我感到困扰,因为我不太了解 EF 的行为和期望。
我有一个 Product、PurchasePrice 和 SalesPrice 实体,我最初的想法是 1 个产品可以有多个 PurchasePrices,但是 1 个 PurchasePrice 只能存在于 1 个产品中(SalesPrice 也是如此)。
因此这些关系:
// NOTE that BaseEntity just has a "int ID" prop and datetimes/stamps
public class Product : BaseEntity
{
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<PurchasePrice> SalesPrices { get; set; }
}
public class PurchasePrice:BaseEntity
{
public Product Product { get; set; }
}
public class SalesPrice:BaseEntity
{
public Product Product { get; set; }
}
现在,让我们向其中添加一个供应商实体,因为这就是我将销售和采购分开并且不从中创建枚举的原因,因为 1 个产品(在数据库中)可以有多个供应商,每个供应商都有自己的拥有 Sales/Purchase 价格 AND 另一个 Productnumber 值。
所以上面变成:
public class Product : BaseEntity
{
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<PurchasePrice> SalesPrices { get; set; }
// added
public ICollection<Supplier> Suppliers { get; set; }
}
public class PurchasePrice:BaseEntity
{
public Product Product { get; set; }
// added
public Supplier Supplier { get; set; }
}
public class SalesPrice:BaseEntity
{
public Product Product { get; set; }
// added
public Supplier Supplier { get; set; }
}
// added Entity Supplier into the party
public class Supplier : BaseEntity
{
public ICollection<Product> Products { get; set; }
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<SalesPrice> SalesPrices { get; set; }
}
让我们继续一点,因为它并不止于此,我想跟踪这些产品-供应商-价格关系,所以我创建了一个名为“ProductSupplierForContract”的实体它将具有以下结构:
public class ProductSupplierForContract:BaseEntity
{
public string ProductnumberValue { get; set; }
public int Product_Id { get; set; }
public int Supplier_Id { get; set; }
public int? Contract_Id { get; set; }
public virtual Product Product { get; set; }
public virtual Supplier Supplier { get; set; }
public virtual Contract Contract { get; set; }
}
最后我有一个 合同 实体,它具有以下结构:
public class Contract:BaseEntity
{
[Required]
public ICollection<Product> Products { get; set; }
public ICollection<ProductSupplierForContract> ProductSupplierForContracts { get; set; }
}
所以乘积变为:
public class Product : BaseEntity
{
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<PurchasePrice> SalesPrices { get; set; }
public ICollection<Supplier> Suppliers { get; set; }
// added
public ICollection<Contract> Contracts { get; set; }
}
自定义种子设定(继承自 DropCreateDatabaseAlways):
protected override void Seed(ApplicationDbContext context)
{
PurchasePrice purchaseprice = new PurchasePrice((decimal)17.70);
ctx.PurchasePrices.Add(purchaseprice);
Product product1 = new Product("test product 1",purchaseprice);
ctx.Products.Add(product1);
base.Seed(ctx);
}
我也有在 Fluent 中定义的映射 API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// setting the Product FK relation required + related entity
modelBuilder.Entity<Entity.ProductSupplierForContract>().HasRequired(psfc => psfc.Product)
.WithMany(p => p.ProductSupplierForContracts)
.HasForeignKey(psfc => psfc.Product_Id);
// setting the Supplier FK relation required + related entity
modelBuilder.Entity<Entity.ProductSupplierForContract>().HasRequired(psfc => psfc.Supplier)
.WithMany(s => s.ProductSupplierForContracts)
.HasForeignKey(psfc => psfc.Supplier_Id);
// setting the Contract FK relation required + related entity
modelBuilder.Entity<Entity.ProductSupplierForContract>().HasOptional(psfc => psfc.Contract)
.WithMany(c => c.ProductSupplierForContracts)
.HasForeignKey(psfc => psfc.Contract_Id);
}
现在,最初我没有遇到任何问题,而且我真的不明白是什么导致了这种突然的变化,以至于我现在在为数据库设置种子时得到了重复的产品。我可以将其简化为只添加一个带有值的简单 PurchasePrice 和一个引用此 PurchasePrice 的 Product,并且有我的副本。
将实体产品的 PurchasePrice class 内的关系更改为 ICollection 不会创建副本,但我不想要此集合,因为它不是多对多关系...
我已经尝试了大量的事情,但没有 "resolved" 这个(如果这是一个开始的问题,对我来说是的,但对 EF 可能不是),比如删除继承 BaseEntity,改变映射(Fluent AND注释), 改变了我播种和初始化一切的方式, 自己定义 ID, 你给它命名 ...
请注意,目的不是优化我播种的方式,而是要有一个体面的工作模型并了解 EF 做什么和它想要什么。
我的问题:
- 为什么这是重复的 occuring/appearing?
如果我希望能够有 1 个实例保持关系
Price-Supplier-Product-Contract,我应该怎么做?
我通过重新设计模型解决了我的问题。我添加了一个额外的实体 ProductForSupplier,它包含产品和供应商以及产品编号的关系。
public class ProductForSupplier:BaseEntity
{
public string ProductnumberValue { get; set; }
[Required]
public Product Product { get; set; }
[Required]
public Supplier Supplier { get; set; }
}
添加了一个实体 ProductsForContract,它将保存一份合同的产品-供应商关系的数量:
public class ProductsForContract
{
public int ProductsForContractId { get; set; }
public int Amount { get; set; }
public ProductForSupplier ProductForSupplier { get; set; }
public Contract Contract { get; set; }
}
并且现有实体 ProductSupplierForContract 变为:
public class ProductSupplierForContract:BaseEntity
{
public ICollection<ProductsForContract> ProductsForContract { get; set; }
[Required]
public Contract Contract { get; set; }
}
这使我可以灵活地保持实体之间的任何类型的关系,并且还处理了重复项(我仍然不知道其原因)。
我用
我因这些问题而产生的问题以及我(需要或不需要)采取的行动让我感到困扰,因为我不太了解 EF 的行为和期望。
我有一个 Product、PurchasePrice 和 SalesPrice 实体,我最初的想法是 1 个产品可以有多个 PurchasePrices,但是 1 个 PurchasePrice 只能存在于 1 个产品中(SalesPrice 也是如此)。
因此这些关系:
// NOTE that BaseEntity just has a "int ID" prop and datetimes/stamps
public class Product : BaseEntity
{
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<PurchasePrice> SalesPrices { get; set; }
}
public class PurchasePrice:BaseEntity
{
public Product Product { get; set; }
}
public class SalesPrice:BaseEntity
{
public Product Product { get; set; }
}
现在,让我们向其中添加一个供应商实体,因为这就是我将销售和采购分开并且不从中创建枚举的原因,因为 1 个产品(在数据库中)可以有多个供应商,每个供应商都有自己的拥有 Sales/Purchase 价格 AND 另一个 Productnumber 值。
所以上面变成:
public class Product : BaseEntity
{
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<PurchasePrice> SalesPrices { get; set; }
// added
public ICollection<Supplier> Suppliers { get; set; }
}
public class PurchasePrice:BaseEntity
{
public Product Product { get; set; }
// added
public Supplier Supplier { get; set; }
}
public class SalesPrice:BaseEntity
{
public Product Product { get; set; }
// added
public Supplier Supplier { get; set; }
}
// added Entity Supplier into the party
public class Supplier : BaseEntity
{
public ICollection<Product> Products { get; set; }
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<SalesPrice> SalesPrices { get; set; }
}
让我们继续一点,因为它并不止于此,我想跟踪这些产品-供应商-价格关系,所以我创建了一个名为“ProductSupplierForContract”的实体它将具有以下结构:
public class ProductSupplierForContract:BaseEntity
{
public string ProductnumberValue { get; set; }
public int Product_Id { get; set; }
public int Supplier_Id { get; set; }
public int? Contract_Id { get; set; }
public virtual Product Product { get; set; }
public virtual Supplier Supplier { get; set; }
public virtual Contract Contract { get; set; }
}
最后我有一个 合同 实体,它具有以下结构:
public class Contract:BaseEntity
{
[Required]
public ICollection<Product> Products { get; set; }
public ICollection<ProductSupplierForContract> ProductSupplierForContracts { get; set; }
}
所以乘积变为:
public class Product : BaseEntity
{
public ICollection<PurchasePrice> PurchasePrices { get; set; }
public ICollection<PurchasePrice> SalesPrices { get; set; }
public ICollection<Supplier> Suppliers { get; set; }
// added
public ICollection<Contract> Contracts { get; set; }
}
自定义种子设定(继承自 DropCreateDatabaseAlways):
protected override void Seed(ApplicationDbContext context)
{
PurchasePrice purchaseprice = new PurchasePrice((decimal)17.70);
ctx.PurchasePrices.Add(purchaseprice);
Product product1 = new Product("test product 1",purchaseprice);
ctx.Products.Add(product1);
base.Seed(ctx);
}
我也有在 Fluent 中定义的映射 API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// setting the Product FK relation required + related entity
modelBuilder.Entity<Entity.ProductSupplierForContract>().HasRequired(psfc => psfc.Product)
.WithMany(p => p.ProductSupplierForContracts)
.HasForeignKey(psfc => psfc.Product_Id);
// setting the Supplier FK relation required + related entity
modelBuilder.Entity<Entity.ProductSupplierForContract>().HasRequired(psfc => psfc.Supplier)
.WithMany(s => s.ProductSupplierForContracts)
.HasForeignKey(psfc => psfc.Supplier_Id);
// setting the Contract FK relation required + related entity
modelBuilder.Entity<Entity.ProductSupplierForContract>().HasOptional(psfc => psfc.Contract)
.WithMany(c => c.ProductSupplierForContracts)
.HasForeignKey(psfc => psfc.Contract_Id);
}
现在,最初我没有遇到任何问题,而且我真的不明白是什么导致了这种突然的变化,以至于我现在在为数据库设置种子时得到了重复的产品。我可以将其简化为只添加一个带有值的简单 PurchasePrice 和一个引用此 PurchasePrice 的 Product,并且有我的副本。
将实体产品的 PurchasePrice class 内的关系更改为 ICollection 不会创建副本,但我不想要此集合,因为它不是多对多关系...
我已经尝试了大量的事情,但没有 "resolved" 这个(如果这是一个开始的问题,对我来说是的,但对 EF 可能不是),比如删除继承 BaseEntity,改变映射(Fluent AND注释), 改变了我播种和初始化一切的方式, 自己定义 ID, 你给它命名 ...
请注意,目的不是优化我播种的方式,而是要有一个体面的工作模型并了解 EF 做什么和它想要什么。
我的问题:
- 为什么这是重复的 occuring/appearing?
如果我希望能够有 1 个实例保持关系 Price-Supplier-Product-Contract,我应该怎么做?
我通过重新设计模型解决了我的问题。我添加了一个额外的实体 ProductForSupplier,它包含产品和供应商以及产品编号的关系。
public class ProductForSupplier:BaseEntity
{
public string ProductnumberValue { get; set; }
[Required]
public Product Product { get; set; }
[Required]
public Supplier Supplier { get; set; }
}
添加了一个实体 ProductsForContract,它将保存一份合同的产品-供应商关系的数量:
public class ProductsForContract
{
public int ProductsForContractId { get; set; }
public int Amount { get; set; }
public ProductForSupplier ProductForSupplier { get; set; }
public Contract Contract { get; set; }
}
并且现有实体 ProductSupplierForContract 变为:
public class ProductSupplierForContract:BaseEntity
{
public ICollection<ProductsForContract> ProductsForContract { get; set; }
[Required]
public Contract Contract { get; set; }
}
这使我可以灵活地保持实体之间的任何类型的关系,并且还处理了重复项(我仍然不知道其原因)。