Entity framework 如果存在子视图,如何使用产品实体
ASP.NET 5 MVC购物车应用程序使用EF核心和Npgsql数据提供程序。 数据库包含产品表Entity framework 如果存在子视图,如何使用产品实体,entity-framework,asp.net-core,entity-framework-core,asp.net-core-mvc,npgsql,Entity Framework,Asp.net Core,Entity Framework Core,Asp.net Core Mvc,Npgsql,ASP.NET 5 MVC购物车应用程序使用EF核心和Npgsql数据提供程序。 数据库包含产品表 create table Product ( Product char(20) primary key; Description char(50); ) 它通过EF Core Scaffold映射到产品实体 public class Product { public string Product1 { get; set; } public string Description
create table Product (
Product char(20) primary key;
Description char(50);
)
它通过EF Core Scaffold映射到产品实体
public class Product {
public string Product1 { get; set; }
public string Description { get; set; }
}
只读产品视图实体具有数据库和产品类中不存在的特殊卷影属性:
public class ShopToode: Product {
public decimal CartPrice { get; set; }
}
public DbSet<ShopToode> ShopToodes { get; set; }
public DbSet<Product> Products { get; set; }
试着得到像这样的产品
var t = ctx.Products.First();
抛出错误
Npgsql.postgresception(0x80004005):42703:t列鉴别器
不存在
如果视图也存在,如何使用产品实体?不确定ShopToode是什么,但听起来像是购物车项目。除非ShopToode需要实际保存到数据库中,否则我不会将其声明为实体,也肯定不会从产品继承。您可以声明要序列化的视图模型或DTO,或将会话变量和项目详细信息从产品中放入其中:
var tooteinfo = await ctx.Products
.Select(x => new TooteInfo
{
ProductId = x.ProductId,
// ...
CartPrice = 1.2
}).ToListAsync();
对于一个持久化到数据的结构,其中我有一个购物车(针对一个用户),CartProduct将一个产品链接到购物车和一个产品,这更适合于多对多关系:
public class Cart
{
[Key]
public int CartId { get; set; }
public int UserId {get; set; }
// ...
public virtual ICollection<CartProduct> CartProducts { get; set; } = new List<CartProduct>();
}
public class CartProduct
{
[Key, Column(Order=0), ForeignKey("Cart")]
public int CartId { get; set; }
[Key, Column(Order=1), ForeignKey("Product")]
public int ProductId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
[NotMapped]
public decimal CartPrice
{
get { return UnitPrice * Quantity; }
}
public virtual Cart Cart { get; set; }
public virtual Product Product { get; set; }
}
public class Product
{
[Key]
public int ProductId { get; set; }
// ...
}
公共类购物车
{
[关键]
公共int-CartId{get;set;}
public int UserId{get;set;}
// ...
公共虚拟ICollection产品{get;set;}=new List();
}
公共类产品
{
[键,列(订单=0),外键(“购物车”)]
公共int-CartId{get;set;}
[键,列(订单=1),外键(“产品”)]
public int ProductId{get;set;}
公共整数数量{get;set;}
公共十进制单价{get;set;}
[未映射]
公价
{
获取{返回单价*数量;}
}
公共虚拟购物车{get;set;}
公共虚拟产品产品{get;set;}
}
公共类产品
{
[关键]
public int ProductId{get;set;}
// ...
}
从那里,您可以查询购物车并从CartProducts中选择详细信息,然后通过CartProducts选择Product以构建视图模型。看起来像是使用手动脚本创建表
Product
?这就是问题所在。如果由EFCore自动生成,则应包含TPH映射的鉴别器列。Product
表包含Product
和ShopToode
的数据,因此它需要一个Discriminator
列来帮助识别每种类型。Product和ShopToode包含相同的产品行。不需要鉴别器不确定您的意思,但如果产品
和ShopToode
在同一个表中,则此处需要鉴别器。事实上,对于这种类型的继承,没有任何配置来指定映射到每个实体类型的单独表,默认情况下将使用每个层次结构的表
方案。该方案始终需要一个鉴别器列,事实上它应该由EFCore生成(并且可以配置为具有不同的名称和类型),除非您使用手动脚本创建表。最后,这个错误说明了一切,它抱怨缺少鉴别器列。在购物车中,产品有大约200个属性,不同商店的属性不同。每家商店在安装时都有不同的产品表和不同等级的脚手架。Datacontext在不同的车间中处于不同的分离组装中。使用ShopToode DTO时,您的代码需要手动硬编码产品属性。这是不可能的。如何创建不需要硬编码属性的代码,如SELECT*,1.2 AS CartPrice FROM Product
。看起来ShopToode应该创建为单独的DTO实体,并且应该只包含对产品实体的引用(产品id),删除继承?
public class Cart
{
[Key]
public int CartId { get; set; }
public int UserId {get; set; }
// ...
public virtual ICollection<CartProduct> CartProducts { get; set; } = new List<CartProduct>();
}
public class CartProduct
{
[Key, Column(Order=0), ForeignKey("Cart")]
public int CartId { get; set; }
[Key, Column(Order=1), ForeignKey("Product")]
public int ProductId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
[NotMapped]
public decimal CartPrice
{
get { return UnitPrice * Quantity; }
}
public virtual Cart Cart { get; set; }
public virtual Product Product { get; set; }
}
public class Product
{
[Key]
public int ProductId { get; set; }
// ...
}