entity-framework - 实体集的关键 - 实体框架
问题描述
我正在尝试从数据库中返回一些值,并且我有两个类Item
和Product
. Item
包含一个Product
和quantity
字段。
在数据库中,有一个名为 的表Items
。正确的使用方法是DbContext
什么?
因为当我试图调用数据酶时,我得到了一个错误
MyStoreProject.Dal.Item:EntityType 'Item' 没有定义键。定义此 EntityType 的键。
items: EntityType: EntitySet 'items' 基于没有定义键的类型'Item'。
是否有另一种方法来定义Item
类的键?
我已经尝试找到正确的方法...所以请您帮忙
System.Data.Entity.ModelConfiguration.ModelValidationException
HResult=0x80131500
Message=在模型生成过程中检测到一个或多个验证错误:MyStoreProject.Dal.Item: : EntityType 'Item' 没有定义键。定义此 EntityType 的键。
items: EntityType: EntitySet 'items' 基于没有定义键的类型'Item'。
代码:
public class ItemDal : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Item>().ToTable("Items");
}
public DbSet<Item> items { get; set; }
}
public class Item
{
[Key]
public Product idproduct { get; set; }
[Required]
public int quantity { get; set; }
}
public class Product
{
[Key]
[Required]
[RegularExpression("^[0-9]{3}$", ErrorMessage = "Product ID must be with 4 numbers")]
public string productId { get; set; }
[RegularExpression("^[a-z]+$", ErrorMessage = "Product Name must be only Characters")]
[StringLength(50, MinimumLength = 2, ErrorMessage = "Product Name must be with a least 2 Characters or Maximum 10 Characters")]
public string name { get; set; }
[Required]
public string description { get; set; }
[Required]
[RegularExpression("^[0-9]{3}$", ErrorMessage = "Price can be with 3 numbers")]
public float price { get; set; }
[Required]
[RegularExpression("^[0-9]{3}$", ErrorMessage = "Class Code can be Only between 1-20")]
public int classCode { get; set; }
public string image { get; set; }
}
这是有例外的代码
ItemDal itemDal = new ItemDal();
Item dbitem = (from x in itemDal.items
where x.idproduct.productId.Equals(id)
select x).ToList<Item>().FirstOrDefault();
解决方案
将实体想象成数据库中的表。如果 Item 是一个实体,那么它应该与数据库中的一个表相关联。您已指定“Item”的主键是 Product 实体。这就像尝试将带有 PK 的 Item 表设置为 Product 表。那样不行。
如果 Item 与 Product 共享一个 PK,即 productId,那么 Item 实体还需要作为 productId 属性来设置它的 [Key] 属性。一个项目也可以有一个 Product 属性,该属性使用该 productId 作为 FK 以一对一的方式映射。
例如:
public class Item
{
[Key]
[ForeignKey("idProduct")]
public string productId { get; set; }
public virtual Product idProduct { get; set; }
}
要按产品 ID 获取项目:
var item = itemDal.items.SingleOrDefault(x => x.productId == id);
要包括产品详细信息:
var item = itemDal.items.Include(x => x.idProduct).SingleOrDefault(x => x.productId == id);
如果 Item 有自己的键 (itemId),则将其定义为 [Key] 并将 productId 保留为外键。这建立了多对一的关系。(许多项目可能引用相同的产品)
public class Item
{
[Key]
public string itemId { get; set; }
[ForeignKey("idProduct")]
public string productId { get; set; }
public virtual Product idProduct { get; set; }
}
然后获取产品的第一个(任意)项目:
var item = itemDal.items.FirstOrDefault(x => x.productId == id);
// or...
var item = itemDal.items.FirstOrDefault(x => x.idProduct.productId == id);
在这种情况下,您可以使用显式映射 (EF6) 或影子属性 (EF Core) 来配置 Item 和 Product 之间的关系,而无需 item 实体中的 productId,但您可以进一步阅读。
如果您只想从数据中获取信息,这一切都很好。如果您想将数据返回到 DbContext (itemDal) 范围之外的视图等,那么您最好使用.Select()
仅使用您需要的详细信息填充一个简单的类,而不是急切/懒惰地加载整个实体。作为一般规则,不要将实体传递到其 DbContext 范围之外(即using()
上下文的块),因为这将对延迟加载产生影响。实体也会给序列化程序带来问题,例如尝试从 MVC 控制器操作中返回它们以获取视图。使用的好处.Select()
是您不必担心显式使用.Include()
访问相关数据。它为您提供了性能改进,因为它减少了要加载和传输的数据量,并且还限制了发送给用户/消费者的有关您的模式的信息。
推荐阅读
- typescript - setInterval 函数在 RxJs 6 + 中不起作用
- c# - 带有数字字符和 # 的 match.regex 语法
- ios - 如何在我的 iPhone 上安装 Flutter 版本的 iOS 应用程序?
- ngrx - 使用带有 ngrx 数据的选择器
- rust - rust 交叉编译 arm:skylake 不是此目标的公认处理器
- sql - Oracle 用户如何在 oracle18c 中查询另一个模式中的表?
- php - 如何对数组中的字符串值求和
- node.js - 如何根据另一个属性选择一个属性 - mongodb
- excel - excel电子表格优化器
- javascript - 未捕获(承诺中)类型错误:无法读取未定义的属性“模式”