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

标签 lambda automapper expression-trees poeaa

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

我想使用查询对象模式(如 Martin Fowler 的企业应用程序架构模式中所命名)来实现这一点,但允许客户端代码使用具有域类型的 lambda 表达式。在幕后,我想将域感知 lambda 表达式转换为数据库感知 lambda 并将此转换后的表达式发送到存储库,以便使用 LINQ to SQL 对数据库执行。

我目前有一个穷人的实现,它将客户端的映射能力限制为简单的属性,但我想将它打开一些更复杂的查询。我不确定我将如何使用 AutoMapper 或任何其他现有的映射工具来解决这个问题,我也不确定 OTTOMH 如何使用自己开发的代码来做到这一点。

这是我想要的功能类型:

// 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) { ... }
}   

最终目标是让这样的事情发挥作用:
// 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));

我的问题真的是这样的,我想:
  • 创建这样的映射器是否可行,如果可行...
  • 使用 AutoMapper 之类的工具是否可行,如果可行...
  • 是否可以利用我已经拥有的 AutoMapper 映射来相互转换 DomainTypeDataEntityType或者我是否需要明确映射 Query<DomainType>Query<DataEntityType> ?

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

    最佳答案

    恕我直言,这个设计看起来很复杂。您是否调查过直接通过 ORM 定义域类型的可能性?毕竟,这就是 ORM 的设计目的......它肯定会打开很多可能性,而无需付出巨大的额外努力......

    很多人不知道Linq 2 SQL居然支持POCO style ,至少在某种程度上?如果您可以考虑其他 ORM 替代方案,那么 NHibernate 和 Entity Framework 都具有更好的 POCO 支持。

    POCO 允许您直接在 ORM 之上定义域模型,但在某种程度上,您的域类可以(或多或少,取决于实际的 ORM)“持久性无知”。因此,您可以利用 ORM 的查询功能向用户公开丰富的域查询 API。

    如果您考虑 Entity Framework (v4),您可能还想查看 WCF Data Services

    只是我的 2 美分...

    关于lambda - 尝试在业务域和数据域之间转换表达式树是否可行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3579741/

    相关文章:

    c++ - 链表的 Lambda 长度

    c++ - 在 map 中使用对 lambda 的引用作为比较器(正确的方法?)

    collections - 使用 AutoMapper 映射只读子集合

    c# - 如何获取泛型表达式中使用的属性类型?

    c++ - 使用 C++ boost::spirit PEG 文法生成表达式

    c# - Lambda 和 Expression.Call 扩展方法

    java - lambda 创建后的序列化

    lambda - kotlin html builder 如何在幕后工作?

    c# - 在自动映射器中使用命名约定和前缀的问题

    c# - 使用 AutoMapper 将值从 object1 复制到 object2