Key for entity set - Entity Framework

0

I'm trying to return some values from the database, and I have two classes Item and Product. Item contains a Product and quantity field.

In the database, there is a table named Items. What is the correct way to use DbContext ?

Because when I'm trying to call the dataase, I'm getting an error

MyStoreProject.Dal.Item: EntityType 'Item' has no key defined. Define the key for this EntityType.
items: EntityType: EntitySet 'items' is based on type 'Item' that has no keys defined.

Is there is another way to define key for the Item class?

I already tried to find for the correct way ...so please your help

System.Data.Entity.ModelConfiguration.ModelValidationException
HResult=0x80131500
Message=One or more validation errors were detected during model generation:

MyStoreProject.Dal.Item: : EntityType 'Item' has no key defined. Define the key for this EntityType.
items: EntityType: EntitySet 'items' is based on type 'Item' that has no keys defined.

Code:

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; }
}

And here is the code with the exception

ItemDal itemDal = new ItemDal();

Item dbitem = (from x in itemDal.items
               where x.idproduct.productId.Equals(id)
               select x).ToList<Item>().FirstOrDefault();
entity-framework
sqlite
model-view-controller
dbcontext
asked on Stack Overflow Apr 28, 2019 by sali weizman • edited Apr 28, 2019 by marc_s

1 Answer

0

Think of entities like you would a table in a database. If Item is an entity, then it should correlate to a table in the database. You've specified that the primary key for "Item" is a Product entity. That's like trying to set up an Item table with a PK to a Product table. Doesn't work that way.

If Item shares a PK with Product, I.e. productId then the Item entity also needs as productId property to set it's [Key] attribute on. An item can also have a Product property which maps as a 1-to-1 using that productId as a FK.

For instance:

public class Item
{
    [Key]
    [ForeignKey("idProduct")]
    public string productId { get; set; }

    public virtual Product idProduct { get; set; }
}

To fetch an item by product ID:

var item = itemDal.items.SingleOrDefault(x => x.productId == id);

To include the product details as well:

var item = itemDal.items.Include(x => x.idProduct).SingleOrDefault(x => x.productId == id);

If Item has it's own key (itemId) then define that as the [Key] and keep the productId as the foreign key. This establishes a many-to-1 relationship. (many Items may reference the same product)

public class Item
{
    [Key]
    public string itemId { get; set; }
    [ForeignKey("idProduct")]
    public string productId { get; set; }

    public virtual Product idProduct { get; set; }
}

Then to fetch the first (arbitrary) item for a product:

var item = itemDal.items.FirstOrDefault(x => x.productId == id);
// or...
var item = itemDal.items.FirstOrDefault(x => x.idProduct.productId == id);

In this case you can configure the relationship between Item and Product without needing the productId in the item entity using an explicit mapping (EF6) or shadow property (EF Core) but you can read up on that further.

This is all good if you just want information from the data. If you want to return data to a view or such outside of the scope of the DbContext (itemDal) then you're best off using .Select() to populate a simple class with just the details you need rather than eager/lazy loading entire entities. As a general rule don't pass entities outside of the scope of their DbContext (I.e. a using() block for the context) as this will have implications for lazy loading. Entities also pose issues for serializers such as attempting to return them from MVC Controller actions for views. The benefit of using .Select() is that you don't need to worry about explicit use of .Include() to access related data. It provides you with a performance improvement as it reduces the amount of data to load and transmit, and also limits the information about your schema that gets sent to a user/consumer.

answered on Stack Overflow Apr 28, 2019 by Steve Py

User contributions licensed under CC BY-SA 3.0