Lambda 尝试在业务域和数据域之间转换表达式树是否可行?

Lambda 尝试在业务域和数据域之间转换表达式树是否可行?,lambda,automapper,expression-trees,poeaa,Lambda,Automapper,Expression Trees,Poeaa,我有一个存储库层,它处理LINQ到SQL自动生成的实体。这些最终被映射到表面上的域友好类型。我现在想为客户机代码提供一些更复杂的查询功能,客户机代码只知道域对象类型 我希望使用查询对象模式(如Martin Fowler的企业应用程序体系结构模式中所述)实现这一点,但允许客户机代码使用域类型的lambda表达式。下面,我想将域感知lambda表达式转换为数据库感知lambda,并将转换后的表达式发送到存储库,以便使用LINQ to SQL对数据库执行 我目前有一个穷人的实现,它将客户机的映射能力限

我有一个存储库层,它处理LINQ到SQL自动生成的实体。这些最终被映射到表面上的域友好类型。我现在想为客户机代码提供一些更复杂的查询功能,客户机代码只知道域对象类型

我希望使用查询对象模式(如Martin Fowler的企业应用程序体系结构模式中所述)实现这一点,但允许客户机代码使用域类型的lambda表达式。下面,我想将域感知lambda表达式转换为数据库感知lambda,并将转换后的表达式发送到存储库,以便使用LINQ to SQL对数据库执行

我目前有一个穷人的实现,它将客户机的映射能力限制为简单属性,但我想将它打开一点,以实现更复杂的查询。我不确定如何使用AutoMapper或任何其他现有的映射工具实现这一点,也不确定如何使用国产代码实现这一点

以下是我想要的功能:

// Example types to be interconverted...
//    DomainId should map to DataEntityId and vice versa
//    DomainName should map to DataEntityName and vice versa
public class DomainType
{
    public int DomainId { get; set; }
    public string DomainName { get; set; }
}
public class DataEntityType
{
    public int DataEntityId { get; set; }
    public string DataEntityName { get; set; }
}

// And this basic framework for a query object.
public class Query<T>
{
    public Query(Func<T, bool> expression) { ... }
    public Func<T, bool> Query { get; }
}

// And a mapper with knowledge about the interconverted query types
public class QueryMapper<TSource, TDestination> 
{
    public void SupplySomeMappingInstructions(
             Func<TSource, object> source, Func<TDestination, object> dest);
    public Query<TDestination> Map(Query<TSource> query);
}

// And a repository that receives query objects
public class Repository<T> 
{
    public IQueryable<T> GetForQuery(Query<T> query) { ... }
}   
//要相互转换的示例类型。。。
//DomainId应该映射到DataEntityId,反之亦然
//DomainName应该映射到DataEntityName,反之亦然
公共类域类型
{
公共int域ID{get;set;}
公共字符串域名{get;set;}
}
公共类DataEntityType
{
public int DataEntityId{get;set;}
公共字符串DataEntityName{get;set;}
}
//这是查询对象的基本框架。
公共类查询
{
公共查询(函数表达式){…}
公共函数查询{get;}
}
//以及一个具有相互转换查询类型知识的映射器
公共类查询映射器
{
public void supplySomeMapping说明(
函数源、函数目标);
公共查询地图(查询);
}
//以及接收查询对象的存储库
公共类存储库
{
公共IQueryable GetForQuery(查询查询){…}
}   
最终目标是让这样的东西发挥作用:

// a repository that is tied to the LINQ-to-SQL types.
var repository = new Repository<DataEntityType>(...);

// a query object that describes which domain objects it wants to retrieve
var domain_query = new Query<DomainType>(item => item.DomainId == 1);

// some mapping component that knows how to interconvert query types
var query_mapper = new QueryMapper<DomainType, DataEntityType>();
query_mapper.SupplySomeMappingInstructions(
                   domain => domain.DomainId, data => data.DataEntityId);
query_mapper.SupplySomeMappingInstructions(
                   domain => domain.DomainName, data => data.DataEntityName);


IQueryable<DataEntityType> results = 
    repository.GetForQuery(query_mapper.Map(domain_query));
//绑定到LINQ到SQL类型的存储库。
var repository=新存储库(…);
//描述要检索哪些域对象的查询对象
var domain_query=新查询(item=>item.DomainId==1);
//一些知道如何相互转换查询类型的映射组件
var query_mapper=new QueryMapper();
query\u mapper.supplySomeMapping说明(
domain=>domain.DomainId,data=>data.DataEntityId);
query\u mapper.supplySomeMapping说明(
domain=>domain.DomainName,data=>data.DataEntityName);
可查询结果=
GetForQuery(query\u mapper.Map(domain\u query));
我的问题是,我认为:

  • 创建这样的映射器可行吗?如果可行
  • 使用AutoMapper这样的工具是否可行,如果可行
  • 是否有可能利用我已经拥有的自动映射来相互转换
    DomainType
    DataEntityType
    ,或者我需要显式地将
    Query
    映射到
    Query

    我最终希望能够灵活地使用不一定是简单对象属性的任意映射函数。

    IMHO,这种设计看起来相当复杂。您是否调查过直接通过ORM定义域类型的可能性?这就是ORM的设计目的,毕竟。。。如果没有这么大的额外努力,它肯定会打开很多的可能性

    很多人不知道LINQ2SQL实际上支持什么,至少在某种程度上是这样的?如果您可以考虑其他ORM替代方案,NHiBiNT和实体框架都有更好的POCO支持。p> POCO允许您直接在ORM之上定义域模型,但是您的域类可以是(或多或少,取决于实际的ORM)“持久性无知”。因此,您可以利用ORM的查询功能向用户公开富域查询API

    如果您考虑实体框架(V4),您可能还需要查看


    只要我的2美分…

    如果要允许针对ViewModels编写LINQ查询并在使用实体模型的存储库中执行它们,还需要签出LINQ表达式树和表达式树转换。AutoMapper在翻译对象时会有所帮助,但您的表达式树也需要翻译


    使用AutoMapper和ExpressionVisitor在此处查看我对类似问题的回答: