Apologies in advance for my naivety.
I am using Entity Framework to persist entities I have defined in my domain model. My domain model entities all inherit from my EntityBase class. This has properties I wish to be common to all my entities:
public class EntityBase
{
public string CreatedBy { get; set; }
public DateTime? Created { get; set; }
public int ModifiedBy { get; set; }
public DateTime? Modified { get; set; }
public bool Enabled { get; set; }
public bool Deleted { get; set; }
}
Now when I want to query EF using LINQ it would be nice if I didn't have to include elements to check if a particular entity is Enabled or Deleted. Every query would involve code, for example:
var messages = _db.Memberships.Where(m => m.UserId.Equals(userId))
.SelectMany(m => m.Group.Messages)
.Include(m => m.Group.Category)
.Select(m => m.Enabled && !m.Deleted)
.ToList();
Rather than doing this each time, I thought I would write an extension method which would act on IQueryable
public static IQueryable<EntityBase> Active(this IQueryable<EntityBase> entityCollection)
{
return entityCollection.Where(e => e.Enabled && !e.Deleted);
}
In my naivety I then thought I could just include this in any LINQ query which returns my entities which inherit from the EntityBase class - like so:
var messages = _db.Memberships.Where(m => m.UserId.Equals(userId))
.SelectMany(m => m.Group.Messages)
.Include(m => m.Group.Category)
.Active() <============================= Extension Methd
.ToList();
return Mapper.Map<List<Message>,List<MessageDto>>(messages);
However, the compiler now complains that:
Error 2 Argument 1: cannot convert from
'System.Collections.Generic.List<Diffusr.Business.Entities.EntityBase>' to
'System.Collections.Generic.List<Diffusr.Business.Entities.Message>'
Question : Can I achieve what I want to achieve, i.e. a common method for all my entities to return only Enabled and not Deleted? If so, how?
Instead of specifying a concrete class, use generics, as most extension methods do:
public static IQueryable<T> Active<T>(this IQueryable<T> entityCollection) where T:EntityBase
{
return entityCollection.Where(e => e.Enabled && !e.Deleted);
}
I assume you are using some version of .NET earlier than 4.0. Generic covariance wasn't allowed before 4.0 (ie passing an enumerable of a child type when an enumerable of the base type was expected).
Even after 4.0, it's not the absolute best idea to use covariance as the compiler ends up doing a lot of extra checks to do to ensure type safety whenever you try to store some new value to the List. Jon Skeet has a nice article about this
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With