将表达式传递给 IEnumerable Select
Passing Expression to IEnumerable Select
我正在尝试编写从数据库实体到应用程序读取模型的自定义映射。
假设我有 2 个实体
public class A
{
public string One {get; set;}
public string Two {get; set;}
public ICollection<B> Three {get;set;}
}
public class B
{
public string SomeProp {get; set;}
public string SomeProp2 {get; set;}
}
我正在尝试映射这些实体以读取模型。
public class AReadModel
{
public string One {get; set;}
public string Two {get; set;}
public ICollection<BReadModel> Three {get;set;}
public bool Deletable {get; set;}
}
public class BReadModel
{
public string SomeProp {get; set;}
public string SomeProp2 {get; set;}
}
此关系中的实体 B 是集合,但在另一个关系中它可以是独立的 1 : 1 或 1 : 0 关系,所以我想将 A 和 AReadModel 以及 B 和 BReadModel 之间的映射定义为将作为表达式传递的IQueryable Select()。关键是我想在 A -> AReadModel 的定义中重用 B -> BReadModel 的映射,并将其定义为 IQueryable 自定义扩展。
public static class BMapping
{
public Expression<Func<B,BReadModel>> expression = instance => new BReadModel
{
SomeProp = instance.SomeProp,
SomeProp2 = instance.SomeProp
};
public static IQueryable<BReadModel>ToReadModel(this IQueryable<B> source)
{
return this.Select(expression);
}
}
public static class AMapping
{
public Expression<Func<A,AReadModel>> expression = instance => new AReadModel
{
One = instance.One,
Two = instance.Any,
Deletable = Three.Any(),
Three = instance.Three.Select(BMapping.expression) // this will not work cuz Three is collection and it requires Func<B,BReadModel> yet i need an expression here, otherwise EF won't be able to translate it. Of course I could just explicitly define mapping here again and it would work but it will lead to maintenance hell.
public static IQueryable<AReadModel>ToReadModel(this IQueryable<A> source)
{
return this.Select(expression);
}
}
所以问题是:是否可以在 AMapping 中嵌套集合的映射定义中重用 BMapping 中定义的映射?
您可以使用 Expression
class 的 Compile()
方法 returns 对应的委托(参见 https://msdn.microsoft.com/en-us/library/bb345362(v=vs.110).aspx)。
通常它需要一些表达式 post 处理,如 LINQKit AsExpandable
/ Invoke
/ Expand
,但幸运的是在这种特定情况下你可以简单地使用AsQueryable
在应用表达式之前,这是最新的 EF6 支持的。
因此,假设 exppression
是 BMapping
class 的静态成员,以下应该有效:
Three = instance.Three.AsQueryable().Select(BMapping.expression)
我正在尝试编写从数据库实体到应用程序读取模型的自定义映射。
假设我有 2 个实体
public class A
{
public string One {get; set;}
public string Two {get; set;}
public ICollection<B> Three {get;set;}
}
public class B
{
public string SomeProp {get; set;}
public string SomeProp2 {get; set;}
}
我正在尝试映射这些实体以读取模型。
public class AReadModel
{
public string One {get; set;}
public string Two {get; set;}
public ICollection<BReadModel> Three {get;set;}
public bool Deletable {get; set;}
}
public class BReadModel
{
public string SomeProp {get; set;}
public string SomeProp2 {get; set;}
}
此关系中的实体 B 是集合,但在另一个关系中它可以是独立的 1 : 1 或 1 : 0 关系,所以我想将 A 和 AReadModel 以及 B 和 BReadModel 之间的映射定义为将作为表达式传递的IQueryable Select()。关键是我想在 A -> AReadModel 的定义中重用 B -> BReadModel 的映射,并将其定义为 IQueryable 自定义扩展。
public static class BMapping
{
public Expression<Func<B,BReadModel>> expression = instance => new BReadModel
{
SomeProp = instance.SomeProp,
SomeProp2 = instance.SomeProp
};
public static IQueryable<BReadModel>ToReadModel(this IQueryable<B> source)
{
return this.Select(expression);
}
}
public static class AMapping
{
public Expression<Func<A,AReadModel>> expression = instance => new AReadModel
{
One = instance.One,
Two = instance.Any,
Deletable = Three.Any(),
Three = instance.Three.Select(BMapping.expression) // this will not work cuz Three is collection and it requires Func<B,BReadModel> yet i need an expression here, otherwise EF won't be able to translate it. Of course I could just explicitly define mapping here again and it would work but it will lead to maintenance hell.
public static IQueryable<AReadModel>ToReadModel(this IQueryable<A> source)
{
return this.Select(expression);
}
}
所以问题是:是否可以在 AMapping 中嵌套集合的映射定义中重用 BMapping 中定义的映射?
您可以使用 Expression
class 的 Compile()
方法 returns 对应的委托(参见 https://msdn.microsoft.com/en-us/library/bb345362(v=vs.110).aspx)。
通常它需要一些表达式 post 处理,如 LINQKit AsExpandable
/ Invoke
/ Expand
,但幸运的是在这种特定情况下你可以简单地使用AsQueryable
在应用表达式之前,这是最新的 EF6 支持的。
因此,假设 exppression
是 BMapping
class 的静态成员,以下应该有效:
Three = instance.Three.AsQueryable().Select(BMapping.expression)