我试图从数据库中返回一些值,我有两个类Item
和Product
。 Item
包含Product
和quantity
字段。
在数据库中,有一个名为Items
的表。使用DbContext
的正确方法是什么?
因为当我试图调用数据库时,我收到了一个错误
MyStoreProject.Dal.Item:EntityType'Part'没有定义键。定义此EntityType的键。 items:EntityType:EntitySet'itements'基于没有定义键的类型'Item'。
是否有另一种方法来定义Item
类的键?
我已经尝试找到正确的方法......所以请你的帮助
System.Data.Entity.ModelConfiguration.ModelValidationException 的HResult = 0x80131500 消息=在模型生成期间检测到一个或多个验证错误:
MyStoreProject.Dal.Item :: EntityType'Item'没有定义键。定义此EntityType的键。 items:EntityType:EntitySet'itements'基于没有定义键的类型'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映射为1对1。
例如:
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之间的关系而不需要productId,但您可以进一步阅读。
如果您只想要数据中的信息,这一切都很好。如果你想将数据返回到DbContext(itemDal)范围之外的视图,那么你最好使用.Select()
来填充一个只需要你需要的细节的简单类,而不是急于/延迟加载整个实体。作为一般规则,不要传递DbContext范围之外的实体(即上下文的using()
块),因为这会对延迟加载产生影响。实体还会给序列化程序带来问题,例如尝试从视图的MVC控制器操作返回它们。使用.Select()
的好处是您不必担心明确使用.Include()
来访问相关数据。它为您提供了性能改进,因为它减少了要加载和传输的数据量,还限制了发送给用户/使用者的架构信息。