1

I used EF fluent API for mapping my POCO classes to database tables. I need to use the mapping configuration in my own application logic. More specifically let say I have entity "Product" and I have the following mapping for this entity:

public class ProductMap : EntityTypeConfiguration<Product>
{
    public ProductMap()
    {
        ....
        this.HasKey(t => t.ProductId);
        ...
    }
}

In my application logic I want to write a generic method which gets the key field of my entity (here ProductId). If I had used the data annotation attributes I could find my key property using reflection. My question is that is it basically possible achive the same when I define my mappings with fluent API?


Thanks diaho. I exactly came to the solution that you suggest but still it is not a good solution since entity framework does not allow us to make query using a field which is not pure entity field. Take the following example: I want to write a generic method which return an entity based on its id. I came to the following solution:

public TModel GetById<TModel, TKey>(TKey id) where TModel : ModelBase<TKey>
{
    return _context.Set<TModel>().where(e => e.Id == id).FirstOrDefault();
}

This code however doesnt work since entity framework complains that e.Id is not a field of drived entity class (its a field of parent class). Of course its possible to hack this issue by converting Set<TModel>() to list (as follow) to force executing query earlier. But this is terrible in terms of performance since it load all entities to memory to retrieve a single one.

public TModel GetById<TModel, TKey>(TKey id) where TModel : ModelBase<TKey>
{
    return _context.Set<TModel>().ToList().where(e => e.Id == id).FirstOrDefault();
}

Do you have better suggestion for this scenario?

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Babak
  • 108
  • 1
  • 8

1 Answers1

0

We ran into a similar scenario. We weren't able to find a great solution, so I'd love to hear feedback. Our solution was to create an abstract ModelBase class which had two fields that were 'common' to all our models:

public abstract class ModelBase<T>
{
    /// <summary>
    /// The id of the model object
    /// </summary>
    public virtual T Id { get; set; }

    /// <summary>
    /// The date the model object was created
    /// </summary>
    public virtual DateTime CreateDate { get; set; }
}

We would then have all our models inherit from that class:

public class Product : ModelBase<int>
{
    public override int Id
    {
        get { return ProductId; }
        set { ProductId = value; }
    }

    public int ProductId { get; set; }
    ...
}

This way you always know the key field of the entity. One note: you will to set your EF database mappings to ignore the Id property

sazh
  • 1,792
  • 15
  • 20