IQueryable with EntityObject using Generics & Interfaces (Possible?)

前端 未结 1 1536
南旧
南旧 2021-01-16 03:46

I have a search repository for EntityFramework 4.0 using LinqKit with the following search function:

public IQueryable Search(Expression<         


        
相关标签:
1条回答
  • 2021-01-16 04:21
    The natural response to this is to actually define the SubsetByUser() method to use a constraint with a GUID property: ... But this doesn't work. I'm using LinqKit and the Expandable() method results in: System.NotSupportedException: Unable to cast the type 'Oasis.DataModel.Arc' to type 'Oasis.DataModel.Interfaces.IHaveMetadata'. LINQ to Entities only supports casting Entity Data Model primitive types

    You're very close with that. You can make this work if you use an ExpressionVisitor that removes all unnecessary casts (casts to a base type or an implemented interface) that are automatically generated.

    public IQueryable<T> SubsetByUser<T>(IQueryable<T> set, User user) 
        where T : IHaveMetadata
    {
        Expression<Func<T, Guid>> GetGUID = arc => arc.GUID;
        GetGUID = (Expression<Func<T, Guid>>)RemoveUnnecessaryConversions.Instance.Visit(GetGUID);
        return set.Join(_searcher.Search<Metadatum>((o) => o.UserGUID == user.GUID),
            GetGUID,
            meta => meta.ElementGUID,
            (arc, meta) => arc);
    }
    
    public class RemoveUnnecessaryConversions : ExpressionVisitor
    {
        public static readonly RemoveUnnecessaryConversions Instance = new RemoveUnnecessaryConversions();
    
        protected RemoveUnnecessaryConversions() { }
    
        protected override Expression VisitUnary(UnaryExpression node)
        {
            if (node.NodeType == ExpressionType.Convert
                && node.Type.IsAssignableFrom(node.Operand.Type))
            {
                return base.Visit(node.Operand);
            }
            return base.VisitUnary(node);
        }
    }
    

    Alternatively, create the expression tree manually using the Expression.* functions, so that you can avoid including the cast in the first place.

    0 讨论(0)
提交回复
热议问题