2017-01-10 18 views
1

Я пытаюсь написать пользовательские сопоставления из объектов db в модели чтения приложений.Передача выражения в IEnumerable Выберите

Давайте предположим, что у меня есть 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 realtionship так я хотел бы определить отображения между А и AReadModel и В и BReadModel в выражениях, которые будут передается как IQueryable Select(). Дело в том, что я хотел бы повторно использовать мое сопоставление для B -> BReadModel при определении A -> AReadModel и определить его как пользовательское расширение 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); 
    } 
} 

Таким образом, вопрос: Можно ли повторно использовать отображение, определенное в BMapping в определении Mapping для вложенной коллекции в AMapping?

+2

ЗАКАНЧИВАТЬ LinqKit. http://www.albahari.com/nutshell/linqkit.aspx – AlexDev

+0

Почему бы вам просто не использовать обычный EF, а затем использовать AutoMapper для преобразования в пользовательские классы. Но то, что я хотел бы знать ... это то, чего вы пытаетесь достичь .. почему ReadModels в первую очередь? – Seabizkit

+0

@Seabizkit Ответ очень прост. EF с Lazy Загрузка загрузите только данные, включенные в Entity. Предположим, что Three Collection сопоставляется с таблицей, и размер этой коллекции (таблицы) будет увеличиваться, по крайней мере, линейным образом во время выполнения приложения (например, A - это тест, а B - TestInstance). Таким образом, у одного теста могут быть тысячи тестовых экземпляров. Я не хочу загружать такую ​​большую коллекцию по моей Entity, но мне нужны некоторые данные, которые можно вычислить только в этой коллекции. (Пример: Deletable = Three.Any()) (дешевый на DB дорогой со стороны приложения) – user2184057

ответ

1

Обычно это требует экспрессии после обработки, как LINQKitAsExpandable/Invoke/Expand, но, к счастью, в этом конкретном случае, вы можете просто использовать AsQueryable перед наклеиванием выражений, который поддерживается последней EF6.

Таким образом, при условии, exppression является статическим членом класса BMapping, должно работать:

Three = instance.Three.AsQueryable().Select(BMapping.expression) 
+0

Спасибо, это именно то, что мне нужно. – user2184057

2

Вы можете использовать метод Compile() класса Expression, который возвращает соответствующий делегат (см. https://msdn.microsoft.com/en-us/library/bb345362(v=vs.110).aspx).

+0

Проблема заключается в том, что EF не работает на делегатах -> Он работает над выражением, если я буду использовать компиляцию, я потеряю всю информацию о дереве выражений, которую требует EF. (Он будет анализировать дерево выражений и не сможет перевести вызов метода ToReadModel). – user2184057

+0

Этот вопрос касается не компиляции кода, а передачи этого выражения таким образом, который позволит Entity Framework перевести его позже. – user2184057