Reputation: 1145
My application contains several business layer types. I create them from Entity Framework entities using linq expressions. Below I put sample code that should describe my current solution. Please consider, that this is only simple example. My real business layer types are much more complex.
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 { .... }
}
}
}
You can notice that ComplexType
creates SimpleType
many times and SimpleType
creation code is duplicated. How can I call linq expression from another expression? I would like to use SimpleType.CreateExpression()
in all places where SimpleType
is created. I use linq expressions, because as I know, expressions are translated to sql queries, so new solution should be also translated to sql queries / compatible with linq to entieties.
Upvotes: 0
Views: 257
Reputation: 14944
I created this Repository https://github.com/jaider/Entity-Expressions that contains @TimEeckhaut EF solution, but a little more reusable/generic library.
Here the database query:
var complexModels = context.ComplexEntities
.Select(EntityExpressionHelper.CreateLambda<ComplexEntity, ComplexModel>())
.ToList();
Here the model looks like:
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; }
}
Upvotes: 1
Reputation: 3702
This first version does not work when used on an IQueryable. (only on an IEnumerable) Scroll to the final version in this post to get the IQueryable-working version.
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)
};
}
}
or if you really want to keep it as an expression to the very end:
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)
};
}
}
Edit: The below code works with entity framework.
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);
}
}
Upvotes: 2