c# - существующей - как установить entity framework




Сущность не может быть построена в запросе LINQ to Entities (9)

В ответ на другой вопрос, который был отмечен как дубликат ( см. Здесь ), я выяснил быстрое и простое решение, основанное на ответе Сорена:

data.Tasks.AddRange(
    data.Task.AsEnumerable().Select(t => new Task{
        creator_id   = t.ID,
        start_date   = t.Incident.DateOpened,
        end_date     = t.Incident.DateCLosed,
        product_code = t.Incident.ProductCode
        // so on...
    })
);
data.SaveChanges();

Примечание. Это решение работает только в том случае, если у вас есть свойство навигации (внешний ключ) в классе Task (здесь называется «Инцидент»). Если у вас этого нет, вы можете использовать одно из других опубликованных решений с помощью «AsQueryable ()».

Существует тип объекта, называемый продуктом, который создается инфраструктурой entity. Я написал этот запрос

public IQueryable<Product> GetProducts(int categoryID)
{
    return from p in db.Products
           where p.CategoryID== categoryID
           select new Product { Name = p.Name};
}

В приведенном ниже коде появляется следующая ошибка:

«Объект или сложный тип Shop.Product не может быть сконструирован в запросе LINQ to Entities»

var products = productRepository.GetProducts(1).Tolist();

Но когда я использую select p вместо select new Product { Name = p.Name}; он работает правильно.

Как я могу создать пользовательский раздел выбора?


Во многих случаях преобразование не требуется. Подумайте по причине, по которой вы хотите строго напечатать List, и оцените, хотите ли вы просто данные, например, в веб-службе или для ее отображения. Это не имеет значения. Вам просто нужно знать, как его читать, и проверить, что это идентично свойствам, определенным в анонимном типе, который вы определили. Это сценарий optimun, вызывающий то, что вам не нужны все поля сущности, и это причина анонимного типа.

Простым способом это делается:

IEnumerable<object> list = dataContext.Table.Select(e => new { MyRequiredField = e.MyRequiredField}).AsEnumerable();

Вы можете использовать это, и он должен работать.> Вы должны использовать toList перед созданием нового списка, используя select:

db.Products
    .where(x=>x.CategoryID == categoryID).ToList()
    .select(x=>new Product { Name = p.Name}).ToList(); 

Вы можете проектировать в анонимный тип, а затем от него до типа модели

public IEnumerable<Product> GetProducts(int categoryID)
{
    return (from p in Context.Set<Product>()
            where p.CategoryID == categoryID
            select new { Name = p.Name }).ToList()
           .Select(x => new Product { Name = x.Name });
}

Изменить : я собираюсь быть более конкретным, так как этот вопрос получил много внимания.

Вы не можете напрямую проектировать в тип модели (ограничение EF), поэтому нет никакого способа обойти это. Единственный способ - проецировать на анонимный тип (1-я итерация), а затем на тип модели (2-я итерация).

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

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

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

Рассмотрите возможный код (желаемый к существованию):

return (from p in Context.Set<Product>()
        where p.CategoryID == categoryID
        select new Product { Name = p.Name }).AsNoTracking().ToList();

Это также может привести к списку отдельных объектов, поэтому нам не нужно будет делать две итерации. Компилятор был бы умен, чтобы увидеть, что AsNoTracking () используется, что приведет к отсоединенным объектам, чтобы оно могло позволить нам это сделать. Если, однако, AsNoTracking () был опущен, он мог бы выбросить то же исключение, что и сейчас, чтобы предупредить нас, что нам нужно быть достаточно конкретным относительно желаемого результата.


Вы не можете (и не должны) проектировать на сопоставленную сущность. Вы можете, однако, проецироваться на анонимный тип или на DTO :

public class ProductDTO
{
    public string Name { get; set; }
    // Other field you may need from the Product entity
}

И ваш метод вернет список DTO.

public List<ProductDTO> GetProducts(int categoryID)
{
    return (from p in db.Products
            where p.CategoryID == categoryID
            select new ProductDTO { Name = p.Name }).ToList();
}

Если вы используете фреймворк Entity, попробуйте удалить свойство из DbContext, которое использует вашу сложную модель как Entity. У меня была такая же проблема при сопоставлении нескольких моделей с моделью вида Entity

public DbSet<Entity> Entities { get; set; }

Удаление записи из DbContext зафиксировало мою ошибку.


Существует еще один способ, которым я нашел работу, вам нужно создать класс, который происходит из вашего класса Product и использовать его. Например:

public class PseudoProduct : Product { }

public IQueryable<Product> GetProducts(int categoryID)
{
    return from p in db.Products
           where p.CategoryID== categoryID
           select new PseudoProduct() { Name = p.Name};
}

Не уверен, что это «разрешено», но оно работает.


вы можете добавить AsEnumerable в свою коллекцию, как показано ниже:

public IQueryable<Product> GetProducts(int categoryID)
{
    return from p in db.Products.AsEnumerable()
           where p.CategoryID== categoryID
           select new Product { Name = p.Name};
}

если вы выполняете Linq to Entity вы не можете использовать ClassType с new при закрытии запроса select only anonymous types are allowed (new without type)

взгляните на этот фрагмент моего проекта

//...
var dbQuery = context.Set<Letter>()
                .Include(letter => letter.LetterStatus)
                .Select(l => new {Title =l.Title,ID = l.ID, LastModificationDate = l.LastModificationDate, DateCreated = l.DateCreated,LetterStatus = new {ID = l.LetterStatusID.Value,NameInArabic = l.LetterStatus.NameInArabic,NameInEnglish = l.LetterStatus.NameInEnglish} })
                               ^^ without type__________________________________________________________________________________________________________^^ without type

из вас добавили new keyword в «Закрытие выбора» даже в complex properties вы получите эту ошибку

поэтому remove ClassTypes from new ключевого слова Linq to Entity запросах Linq to Entity ,

потому что он преобразуется в sql-оператор и выполняется на SqlServer

поэтому когда я могу использовать new with types при select закрытия?

вы можете использовать его, если вы имеете дело с LINQ to Object (in memory collection)

//opecations in tempList , LINQ to Entities; so we can not use class types in select only anonymous types are allowed
var tempList = dbQuery.Skip(10).Take(10).ToList();// this is list of <anonymous type> so we have to convert it so list of <letter>

//opecations in list , LINQ to Object; so we can use class types in select
list = tempList.Select(l => new Letter{ Title = l.Title, ID = l.ID, LastModificationDate = l.LastModificationDate, DateCreated = l.DateCreated, LetterStatus = new LetterStatus{ ID = l.LetterStatus.ID, NameInArabic = l.LetterStatus.NameInArabic, NameInEnglish = l.LetterStatus.NameInEnglish } }).ToList();
                                ^^^^^^ with type 

после того, как я выполнил ToList по запросу, он стал in memory collection поэтому мы можем использовать new ClassTypes в select





entity-framework