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 ?

1
  • Do you have compile errors or the query doesn't get what you want ? Commented Mar 6, 2014 at 23:23

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Do you have sample for adding a bas class as per your recommendation
It seems there's no such question on stackoverflow, so I decided to ask this question. Look at this link.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.