3

I have the following two classes auto generated with Entity Framework using database first;

public partial class UserXml
{
    public UserXml()
    {
        this.UserXmlHotel = new HashSet<UserXmlHotel>();
    }

    public long UserId { get; set; }
    public string Password { get; set; }
    public bool Enabled { get; set; }
    public byte FailedAttempt { get; set; }

    public virtual User User { get; set; }
    public virtual UserXmlIp UserXmlIp { get; set; }
    public virtual ICollection<UserXmlHotel> UserXmlHotel { get; set; }
}

and

public partial class UserCustomer 
{
    public UserCustomer ()
    {
        this.UserCustomerHotel = new HashSet<UserCustomerHotel >();
    }

    public long UserId { get; set; }
    public bool Enabled { get; set; }
    public string Password { get; set; }
}

I've then created the following classes;

public partial class UserXml : IUser
{
}

public partial class UserCustomer : IUser
{
}

public static class EntityExtensions
{
    public static IQueryable<T> Enabled<T>(this IQueryable<T> source) where T : IUser
    {
        return source.Where(x => x.Enabled);
    }
}

I have a interface as;

public interface IUser
{
    bool Enabled { get; }
}

Want I'm wanting to do is combine the same call for each entity using the same re-usable code; So take

using(var Context = new EscapeEntities())
{
     bool bEnabled = Context.UserXml.First(u => u.UserId == iUserId).Enabled;
}

and

using(var Context = new EscapeEntities())
{
     bool bEnabled = Context.UserCustomer.First(u => u.UserId == iUserId).Enabled;
}

I'm wanting to use my EntityExtensions class, but I'm having trouble getting it to work. Any pointers ?

neildt
  • 5,101
  • 10
  • 56
  • 107

1 Answers1

4

When you use expressions on generic types which implement an interface, the expression builder adds a cast to the expression, like below:

x => x.Enabled // converts to something like below: 
x => ((IUser)x).Enabled

So what you need to do is to tell the expression builder to not add the cast expression by defining your generic type as a class, which means your Enabled(...) extension method needs to be like this:

public static IQueryable<T> Enabled<T>(this IQueryable<T> source) 
  where T : class, IUser // added 'class' constraint
{
    return source.Where(x => x.Enabled);
}

Another approach (which needs much more work) is to define an ExpressionVisitor class to remove the convert on the expression which is explained on this stackoverflow answer.

So after this correction, you can user your extension method easily:

using(var Context = new EscapeEntities())
{
    IQueryable<UserXml> query = Context.UserXml
        .Where(u => u.Password == "Foo")).Enabled();
    List<UserXml> res = query.ToList();
}

P.S. I think you'd be better off with defining another extra "base" User table with two children named UserXml and UserCustomer and abstract out the common columns into User table, which removes the need for extra interfaces and is also compatible with object oriented design.

Community
  • 1
  • 1
Ashkan
  • 3,322
  • 4
  • 36
  • 47
  • Thanks. Do you have sample for adding a bas class as per your recommendation – neildt Mar 07 '14 at 06:58
  • It seems there's no such question on stackoverflow, so I decided to ask this question. Look at [this link](http://stackoverflow.com/a/22263190/1126168). – Ashkan Mar 08 '14 at 00:24