2010-08-26 4 views
4

У меня есть слой репозитория, который связан с объектами с автогенерированием LINQ to SQL. В конечном итоге они отображаются на поверхности, удобные для использования на поверхности. Теперь я хотел бы предоставить несколько более сложных запросов для клиентского кода, и этот код клиента знает только о типах объектов домена.Можно ли попытаться преобразовать деревья выражений между доменами бизнеса и данных?

Я хотел бы реализовать это с помощью шаблона объекта запроса (как указано в шаблонах архитектуры корпоративного приложения Мартина Фаулера), но позволяет клиентскому коду использовать лямбда-выражения с типами доменов. Под обложками я хотел бы преобразовать выражение 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)); 

Мои вопросы действительно это, я думаю:

  1. Возможно ли создание такого картографа, и если да, то ...
  2. ли это возможно сделать это с помощью инструмента, как AutoMapper, и если это так ...
  3. Можно ли воспользоваться отображением AutoMapper, что у меня уже есть, что interconverts DomainType и DataEntityType или же мне нужно явно отобразить Query<DomainType> в Query<DataEntityType>?

Я в конечном счете хочу сделать это, чтобы иметь гибкость при использовании произвольных функций отображения, которые не обязательно являются простыми свойствами объекта.

+0

Смотрите мой ответ на аналогичный вопрос здесь, используя AutoMapper и ExpressionVisitor: http://stackoverflow.com/questions/7424501/automapper-for-funcs-between-selector-types/7425211#7425211 – luksan

ответ

1

ИМХО, этот дизайн выглядит довольно сложным. Вы исследовали возможность определения ваших доменных типов непосредственно через ORM? Это то, для чего ORM предназначен, в конце концов ... Это, несомненно, откроет возможности большого количества возможностей без этих огромных дополнительных усилий ...

Многие люди не знают, что LINQ 2 SQL фактически поддерживает POCO style, по крайней мере, некоторым степени? Если вы можете рассмотреть другие альтернативы ORM, обе NHibernate и Entity Framework имеют лучшую поддержку POCO.

POCO позволяет вам определить вашу модель домена непосредственно поверх ORM, но таким образом, чтобы ваши классы домена могли (более или менее, в зависимости от фактического ORM) «сохраняться невежественными». Таким образом, вы можете использовать возможности запросов ORM для предоставления пользователям запросов API запросов с богатым доменом.

Если бы рассмотреть Entity Framework (v4), вы также можете захотеть взглянуть на WCF Data Services

Просто мои 2 цента ...

0

Если вы хотите разрешить запросы LINQ, написанные против ViewModels, и выполнять их в репозитории, который использует модели сущностей, вам также необходимо проверить деревья выражений LINQ и трансляцию дерева выражений. AutoMapper будет полезен при переводе объектов, но ваши деревья выражений также потребуют перевода.

http://blogs.msdn.com/b/charlie/archive/2008/01/31/expression-tree-basics.aspx