首页 > 解决方案 > 实体集的关键 - 实体框架

问题描述

我正在尝试从数据库中返回一些值,并且我有两个类ItemProduct. Item包含一个Productquantity字段。

在数据库中,有一个名为 的表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();

标签: entity-frameworksqlitemodel-view-controllerdbcontext

解决方案


将实体想象成数据库中的表。如果 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()访问相关数据。它为您提供了性能改进,因为它减少了要加载和传输的数据量,并且还限制了发送给用户/消费者的有关您的模式的信息。


推荐阅读