Как я могу избежать исключения NotSupportedException? - PullRequest
0 голосов
/ 25 февраля 2019

Я читаю эту статью: Сущность не может быть создана в запросе LINQ to Entities , но, думаю, она не полностью связана с моей проблемой.

У меня есть этот код:

public class Class1
{
        public string Prop1 { get; set; }
        public string Prop2 { get; set; }
        public string Prop3 { get; set; }
}

[Table("Class2")]
public class Class2
{
        [Key]
        [Column("Prop1")]
        public string Prop1 { get; set; }

        [Column("Prop2")]
        public string Prop2 { get; set; }

        [Column("Prop3")]
        public string Prop3 { get; set; }
}

и метод редактирования, где я хочу использовать следующие:

using (var data = new Context())
{
    var config = data.Class2.FirstOrDefault(c => c.Prop1.Contains(some_string));
    if (config != null)
    {
        config.Prop1 = class1_instance.Prop1;
        config.Prop2 = class1_instance.Prop2;
        config.Prop3 = class1_instance.Prop3;
    }
    data.Entry(config).State = EntityState.Modified;
    data.SaveChanges();
}

Итак, я хочу получить упрощенное редактирование,вместо того, чтобы присваивать каждому свойству одно за другим, я хочу написать что-то вроде config = class1_instance;

Так что я унаследовал Class1 от Class2, но получил

System.NotSupportedException(сущность или сложный тип "Class1" не могут быть созданы в запросе Linq to Entities).

Как с этим справиться?

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Теперь Class1 и Class2 имеют одинаковые свойства.Предназначено ли это, или это случайно, и может ли быть так, что будущие версии Class2 будут иметь свойства, которых нет в Class1?

В каркасе сущностей DbSet<...> представляет таблицы вашей базы данных,класс в DbSet представляет одну строку в таблице.Столбцы вашей таблицы являются не виртуальными свойствами класса;виртуальные свойства представляют отношения между таблицами (один ко многим, многие ко многим, ...)

Class2 представляет таблицу базы данных.Если Class1 должен быть равен Class2, то в чем причина для Class1.Если это равенство существует только сейчас, а в будущих версиях они могут отличаться, вам придется копировать свойства по одному.

void UpdateValue(string someString, Class1 value)
{
    using (var dbContext = new DbContext())
    {
        Class2 fetchedData = dbContext.Class2.Where(...).FirstOrDefault();
        if (fetchedData != null)
        {   // data exists. Update the properties
            fetchedData.Prop1 = value.Prop1,
            fetchedData.Prop2 = value.Prop2,
            fetchedData.Prop3 = value.Prop3,

            // future version of Class2 may have properties that are not updated
            // no need to set state to modified. Entity Framework will detect the changes
            dbContext.SaveChanges();
        }
    }
}

Если вы абсолютно уверены, что каждый Class2особый тип Class1, сейчас и в далеком будущем, вы можете подумать о том, чтобы получить Class2 из Class1:

class Class2 : Class1
{
    public int Id {get; set;}
    ... // properties that are in Class2, but not in Class1
}

Это означает, что каждое не виртуальное свойство Class1 представлено столбцом в таблицах.с классами 2.

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

0 голосов
/ 25 февраля 2019

Не наследуйте класс DTO от класса сущности, потому что EF6 будет рассматривать DTO как сущность, участвующую в некоторых поддерживаемых стратегиях наследования базы данных.

Вместо этого используйте SetValues ​​(объект) из DbPropertyValues, возвращаемого свойством CurrentValues DbEntityEntry:

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

например

Class1 source = ...;
var target = data.Class2.FirstOrDefault(...);
if (target != null)
{
    data.Entry(target).CurrentValues.SetValues(source);
    data.SaveChanges();
}

Обратите внимание, что целевой объект уже присоединен (отслежен)контекст БД, поэтому нет необходимости устанавливать состояние входа на Modified.

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