Наследование LINQ "Down-Cast" с новым свойством - PullRequest
2 голосов
/ 22 ноября 2011

У меня есть два следующих класса:

public class Base
{
    public int Id { get; set; }
    public string PropertyA { get; set; }
}

[NotMapped]
public class Derived : Base
{
    public string PropertyB { get; set; }
}

И у меня есть следующий запрос:

var baseQ = from b in db.Bases
            let propertyB = SomeCalculation()
            select new { Base = b, PropertyB = propertyB };

Это работает как есть.То, что я хочу, это что-то вроде этого (псевдокод):

List<Derived> list =  (from b in db.Bases
                      let propertyB = SomeCalculation()
                      select new { Base = b, PropertyB = propertyB }).ToList();

Можно ли выполнить "Down-Cast" выбор к производному классу, или мне нужно написать конструктор для класса Derivedкоторый выглядит примерно так:

public Derived(Base b, string b) { ... }

Мое окончательное решение : я изменил производный класс на следующий (поскольку вы даже не можете использовать строку. Формат в инициализаторе объекта):

public class Derived
{
    public Base Base { get; set; }
    public string PropertyB { get; set; }

    public string CalculatedProperty { get { ... } }//For string.Format and other stuff
}

И я выполняю задание следующим образом:

List<Derived> list =  (from b in db.Bases
                      let propertyB = SomeCalculation()
                      select new Derived { Base = b, PropertyB = propertyB }).ToList();

Ответы [ 3 ]

3 голосов
/ 22 ноября 2011

Вы не можете привести в этом случае, так как ваш запрос возвращает анонимный тип.Вместо этого вы можете использовать инициализатор объекта для установки свойств в класс Derived:

List<Derived> list = (from b in db.Bases
                     let propertyB = SomeCalculation()
                     select new Derived
                     {
                         Id = b.Id,
                         PropertyA = b.PropertyA,
                         PropertyB = propertyB
                     }).ToList();

Если у вас есть масса свойств, вы можете воспользоваться предложенным вами подходом или добавить объект передачи данных (DTO), который содержит ваши свойства, затем используйте библиотеку, такую ​​как AutoMapper, чтобы выполнить сопоставление для вас.

1 голос
/ 23 ноября 2011
List<Derived> list = db.Bases.ToList()
.Select(p => new Derived()
                 {
                     Id = b.Id,
                     PropertyA = b.PropertyA,
                     PropertyB =  SomeCalculation(),
                 }).ToList();;
0 голосов
/ 24 ноября 2011

Принятый ответ не сработает, потому что EF не позволит вам создавать конкретные типы в базе данных. Обходной путь - он позволяет вам выбирать анонимные типы.

Опираясь на ответ Ахмада:

var aList = (from b in db.Bases
             let propertyB = SomeCalculation()
             select new 
             {
                 Id = b.Id,
                 PropertyA = b.PropertyA,
                 PropertyB = propertyB
             }).ToList(); 

List<Derived> list = (from a in aList
                      select new Derived
                      {
                          Id = a.Id,
                          PropertyA = a.PropertyA,
                          PropertyB = a.PropertyB
                      }).ToList(); 

Вызов ToList по вашему запросу заставляет выполнить запрос и данные, которые будут извлечены в ваше приложение (т.е. он больше не будет выполняться в базе данных). aList теперь является списком в памяти, поэтому вы можете выбирать элементы в новые Derived объекты.

Проще говоря, проблема в том, что все, до тех пор, пока вы не вызовете ToList, скомпилировано в SQL-запрос (для повышения эффективности). Обычно это хорошо, но проблема в том, что ваша база данных не имеет понятия Derived и запрос select new Derived не может быть преобразован в SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...