【问题标题】:Calling linq expression in other linq expression在其他 linq 表达式中调用 linq 表达式
【发布时间】:2014-12-22 11:42:51
【问题描述】:

我的应用程序包含多种业务层类型。我使用 linq 表达式从 Entity Framework 实体创建它们。下面我放置了应该描述我当前解决方案的示例代码。请考虑,这只是一个简单的例子。我真正的业务层类型要复杂得多。

public class SimpleType
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public static Expression<Func<simple_type_entity, SimpleType>> CreateExpression()
    {
        return arg => new SimpleType
        {
            Id = arg.id,
            Name = arg.name,
            Description = arg.desc
        }
    }
}
public class ComplexType
{
    public Guid Id { get; set; }
    public SimpleType Property1 { get; set; }
    public SimpleType Property2 { get; set; }

    public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
    {
        return arg => new ComplexType
        {
            Id = arg.id,
            Property1 = new SimpleType 
            { 
                Id = arg.property1.id, 
                Name = arg.property1.name,   
                Description = arg.property1.desc
            },
            Property2 = new SimpleType { .... }
        }
    }
}

您可以注意到ComplexType 多次创建SimpleType 并且SimpleType 创建代码是重复的。如何从另一个表达式调用 linq 表达式?我想在创建SimpleType 的所有地方使用SimpleType.CreateExpression()。我使用 linq 表达式,因为据我所知,表达式被转换为 sql 查询,所以新的解决方案也应该被转换为 sql 查询/与 linq to entieties 兼容。

【问题讨论】:

    标签: c# .net entity-framework linq-to-entities


    【解决方案1】:

    第一个版本在 IQueryable 上使用时不起作用。 (仅在 IEnumerable 上) 滚动到本文中的最终版本以获取 IQueryable-working 版本。

    public class ComplexType
    {
        public Guid Id { get; set; }
        public SimpleType Property1 { get; set; }
        public SimpleType Property2 { get; set; }
    
        public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
        {
            var compiledSimpleTypeFnc = SimpleType.CreateExpression().Compile();
            return arg => new ComplexType
            {
                Id = arg.id,
                Property1 = compiledSimpleTypeFnc(arg.property1),
                Property2 = compiledSimpleTypeFnc(arg.property2)
            };
        }
    }
    

    或者如果你真的想把它作为一个表达式保留到最后:

    public class ComplexType
    {
        public Guid Id { get; set; }
        public SimpleType Property1 { get; set; }
        public SimpleType Property2 { get; set; }
    
        public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
        {
            var expr = SimpleType.CreateExpression();
            return arg => new ComplexType
            {
                Id = arg.id,
                Property1 = expr.Compile()(arg.property1),
                Property2 = expr.Compile()(arg.property2)
            };
        }
    }
    

    编辑:以下代码适用于实体框架。

    using System;
    using System.Linq.Expressions;
    using ConsoleApplication2;
    using System.Linq;
    
    class Program2
    {
        public static void Main(string[] args)
        {
            using (var db = new TestEntities())
            {
                var exp = db.complex_type_entity.Select(ComplexType.CreateExpression()).First();
            }
        }
    }
    
    public class SimpleType
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    
        public static Expression<Func<simple_type_entity, SimpleType>> CreateExpression()
        {
            var parameterExpr = Expression.Parameter(typeof(simple_type_entity), "p0");
            return Expression.Lambda<Func<simple_type_entity, SimpleType>>(CreateExpression(parameterExpr), parameterExpr);
        }
    
        public static MemberInitExpression CreateExpression(Expression sourceExpr)
        {
            return Expression.MemberInit(
                Expression.New(typeof(SimpleType)),
                Expression.Bind(typeof(SimpleType).GetProperty("Id"), Expression.Property(sourceExpr, "id")),
                Expression.Bind(typeof(SimpleType).GetProperty("Name"), Expression.Property(sourceExpr, "name")),
                Expression.Bind(typeof(SimpleType).GetProperty("Description"), Expression.Property(sourceExpr, "desc")));
        }
    }
    
    public class ComplexType
    {
        public Guid Id { get; set; }
        public SimpleType Property1 { get; set; }
        public SimpleType Property2 { get; set; }
    
        public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
        {
            var parameterExp = Expression.Parameter(typeof(complex_type_entity), "p0");
    
            return Expression.Lambda<Func<complex_type_entity, ComplexType>>(
                Expression.MemberInit(
                    Expression.New(typeof(ComplexType)),
                    Expression.Bind(typeof(ComplexType).GetProperty("Id"), Expression.Property(parameterExp, "id")),
                    Expression.Bind(typeof(ComplexType).GetProperty("Property1"), SimpleType.CreateExpression(Expression.Property(parameterExp, "simple_type_entity"))),
                    Expression.Bind(typeof(ComplexType).GetProperty("Property2"), SimpleType.CreateExpression(Expression.Property(parameterExp, "simple_type_entity1")))),
            parameterExp);
        }
    }
    

    【讨论】:

    • 它不适用于 linq to entieties。我收到异常:“LINQ to Entities 不支持 LINQ 表达式节点类型 'Invoke'。”
    • codemonkey - 在我看来,您已删除最后一条评论。 ;)
    • 我确实做到了。我用一个工作版本编辑了我的答案......享受:)
    • 哇...谢谢您的回答,但是...我不确定是否要使用您的解决方案:P。甚至为你投票。但我仍在寻找更好的解决方案。
    • 最后一件事。您的第一个解决方案适用于 IEnumerable,但使用 IQueryable 会引发异常。所以它没有编译成sql查询。如果我错了,请纠正我。
    【解决方案2】:

    我创建了这个存储库https://github.com/jaider/Entity-Expressions,其中包含@TimEeckhaut EF 解决方案,但更多的是可重用/通用库。

    这里是数据库查询:

    var complexModels = context.ComplexEntities
                    .Select(EntityExpressionHelper.CreateLambda<ComplexEntity, ComplexModel>())
                    .ToList();
    

    这里的模型看起来像:

    public class ComplexModel
    {
        [EntityExpression(nameof(ComplexEntity.Id))]
        public Guid Id { get; set; }
    
        [EntityExpression(nameof(ComplexEntity.Property1), IsComplex = true)]
        public SimpleModel Property1 { get; set; }
    
        [EntityExpression(nameof(ComplexEntity.Property2), IsComplex = true)]
        public SimpleModel Property2 { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      相关资源
      最近更新 更多