powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / EF: Защитить сущность от изменений
25 сообщений из 44, страница 1 из 2
EF: Защитить сущность от изменений
    #38815557
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гуглил, но, видимо, не то или не так.

В общем, хотелось бы при выборке сущности или коллекции сущностей пометить их как-то только для чтения. Просто для страховки от ошибок в алгоритме. То есть, есть, к примеру, метод, который получает в распоряжение какое-то количество сущностей, меняет, скажем, только одну, и вызывает Save на контексте. Если алгоритм случайно изменил сущности, которые ему выдали в распоряжение "только для чтения", то их изменение приведет (скажем) к исключению при сохранении или еще какому-то блокирующему поведению.

Есть ли в EF что-то в таком духе?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38815559
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только AsNoTracking для всего сета.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38815565
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУТолько AsNoTracking для всего сета.Собственно, мне и нужно для сета.

Я правильно понял, что если я сделаю MySet.AsNoTracking().SingleOrDefault(....), полученная единственная сущность также не будет отслеживаться контекстом?

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

Есть ли какие-то неприятные побочные явления у этого метода (ну типа, материализация, производительность и т.п.)?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38815599
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProЯ правильно понял, что если я сделаю MySet.AsNoTracking().SingleOrDefault(....), полученная единственная сущность также не будет отслеживаться контекстом?
Да.

Shocker.ProЯ правильно понял, что я не получу исключения при сохранении, просто изменения таких сущностей будут проигнорированы?
Да.

Shocker.ProЕсть ли какие-то неприятные побочные явления у этого метода (ну типа, материализация, производительность и т.п.)?
Наоборот, при отключенном трекинге производительность выше. Можно влиять на трекинг либо на уровне сетов через AsNoTracking, либо на уровне всего контекста через AutoDetectChangesEnabled. Иметь же один сет с вперемешку включенным и отключенным трекингом на уровне отдельных сущностей нельзя.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38815679
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38821746
Gluck_13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro,

ObjectContext.SavingChanges event
в http://msdn.microsoft.com/ru-ru/library/system.data.objects.objectcontext.savingchanges(v=vs.110).aspx
как раз подходящий пример, который производит валидацию и выкидывает exception.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38821750
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
спасибо, гляну
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38821934
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gluck_13Shocker.Pro,

ObjectContext.SavingChanges event
в http://msdn.microsoft.com/ru-ru/library/system.data.objects.objectcontext.savingchanges(v=vs.110).aspx
как раз подходящий пример, который производит валидацию и выкидывает exception.

Это да, но зачем эту сущность вообще отслеживать в трекере?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870353
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще проблемка.
Пытаюсь получить доступ к измененным сущностям перед тем, как вызову SaveChanges()
Код: c#
1.
2.
3.
4.
        foreach (var manager in db.ChangeTracker.Entries().Where(n =>
            n.State.In(EntityState.Added, EntityState.Modified) &&
            ......
          ))


Пока в контексте не было NoTracking объектов, этот код работал, когда они там стали появляться, метод Entries генерит исключение:The object in the ' мой_notracking_тип ' role cannot be automatically added to the context because it was retrieved using the NoTracking merge option. Explicitly attach the entity to the ObjectContext before defining the relationship.не догоняю, что мне с этим сделать, как получить список измененных сущностей
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870406
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro,

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

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
public class SomeEntity
{
   public long Id {get;set;}
   public string Name {get;set;}
   ...
}

...

public class SomeEntityDto
{
   public long Id {get;set;}
   public string Name {get;set;}
}

...

internal class SomeDal : ISomeDal
{

...

// с использованием AutoMapper
public IReadOnlyCollection<SomeEntityDto> GetSomeCollection(...) 
{
   return this.Context.Set<SomeEntity>().Project().To<SomeEntityDto>().ToList();
}

// без использования AutoMapper
public IReadOnlyCollection<SomeEntityDto> GetSomeCollection(...) 
{
   return this.Context.Set<SomeEntity>()
     .Select(p => new SomeEntityDto
     {
         Id = p.Id,
         Name = p.Name
     })
     .ToList();
}

...

}



Вот и всё. Плюсы -- не надо ковырять EF и его потроха, независимость от источника данных (в целом, это вообще может быть не DbContext, а простой List, что очень удобно для юнит-тестов, или вообще что-то другое, лишь поддерживало IQueryable), ты получаешь только те данные, что тебе надо (именно тот набор полей) и не можешь ничего изменить случайно ни при каких обстоятельствах, т.е. без всяких допущений, что там дескать должен работать AsNoTracking.

Считаю, что AsNoTracking-у место только в узкоспециализированных решениях, в разработке прикладных со слоем бизнес-логики от него в итоге больше проблем, чем пользы.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870419
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Разобрался через ObjectContext.ObjectStateManager.GetObjectStateEntries

Только нифига не понял, мой контекст наследует DbContext-у
DbContext реализует IObjectContextAdapter, таким образом должен иметь свойство ObjectContext

Однако, Intellisense мне его не выдает, пока я явно не приведу db к IObjectContextAdapter, компиляция тоже не проходит без приведения, почему так?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870434
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,
Доводы ясны, но есть другие соображения, о них позже.

Подскажи тогда плиз, как правильно сделать.
У сущности есть навигационное свойство "многие-ко-многим", в виде virtual List<MyEntityType>

При создании/редактировании экземпляра сущности, у меня есть коллекция id-шников внешнего ключа. Как мне правильно заполнить это свойство?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870444
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Похоже, список MyEntityType при редактировании отношения многие-ко-многим нельзя получать AsNoTracking, ибо они тоже должны сохраняться (хотя фактически происходит перезапись только таблицы отношений, но для EF сущности "на том конце" считаются как бы модифицированными)
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870590
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProОднако, Intellisense мне его не выдает, пока я явно не приведу db к IObjectContextAdapter, компиляция тоже не проходит без приведения, почему так?

Потому что интерфейс реализован явно (explicit) (т.е. требуется приведение к интерфейсу).

Shocker.ProПодскажи тогда плиз, как правильно сделать.
У сущности есть навигационное свойство "многие-ко-многим", в виде virtual List<MyEntityType>

При создании/редактировании экземпляра сущности, у меня есть коллекция id-шников внешнего ключа. Как мне правильно заполнить это свойство?

Возможно это покажется неудобным, но с помощью одного ключа добавить связь так просто не удастся. Требуется получить экземпляр сущности, затем добавить в коллекцию. Другой способ (которым лучше не пользоваться), это создать новый экземпляр с нужным Id (остальные поля определять не надо), приатачить его к контексту , затем добавит в коллекцию навигационного свойства.

Я стараюсь избегать нативной реализации М:М, предлагаемой EF. Вместо этого я сам определяю таблицу двухсторонней связи, это хорошо тем, что контроля больше, в связь можно добавить атрибуты (хотя бы даже время установки связи и кем она сделана), и не надо так морочиться, можно использовать чистые Id, без свистоплясок. Но если такой возможности нет, то как я сказал выше.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870613
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttи не надо так морочитьсяНу, хорошо, у тебя есть лишняя сущность - связка.
А => ММ <= Б
Таким образом, при перезаписи сущности А тебе не надо дергать сущности Б.
Нужно грохнуть все сущности ММ, связанные с А, создать новую коллекцию сущностей ММ (ссылка на Б прописывается через ММ.Б_Id)
Как вариант, грохнуть только удаленные сущности ММ, неизменившиеся подгрузить и добавить только новые.

Ну и обслуживать эти связки их нужно, создавать, управлять....

Вроде как, мороки больше. Опять же, ты же вроде сторонник по максимуму использовать возможности EF ))
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38870820
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProНу и обслуживать эти связки их нужно, создавать, управлять....

Не нужно обслуживать эти связки, работаешь с ними точно также, через навигационные свойства. Просто по сути, связь это тоже своего рода объект. Она тоже может обладать атрибутами. Допустим, у товара есть аналоги и рекомендованные для покупки с ним товары. По определению аналог не может быть рекомендованным товаром, следовательно задача решается всего одной связью с типом связи, а не двумя отдельными, за которыми придётся дополнительно следить.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public class ProductRelation
{
   [Key, Column(Order = 0)]
   public long ProductId {get;set;}
   public Product Product {get;set;}

   [Key, Column(Order = 1)]
   public long RelatedId {get;set;}
   public Product Related {get;set;}

   public ProductRelationType RelationType {get;set;}
}



Составной ключ, такой же как и в «нативной» М:М, что значит каскад и отдельного сопровождения не требуется. Такой способ связи проще развивать. Например, можно связи физически не удалять, сохраняя историю, сохранять информацию о дате создания и пользователе, создавшем связи и другую мета-информацию, расширять типы связей, получая таким образом больше контроля над данными.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38878549
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttпросто воспользуйся отражениемА вот скажи, как ты поступаешь, когда членов много? Используешь какой-то кодогенератор? А при модернизации сущности?

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

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

ЗЫ: Дополнительный вопрос - в твоем примере с автомаппером - сработает ли оптимизация, и данные разных сущностей из БД будут получены одним запросом с join-ом?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38878586
ViPRos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

и тут миграцию хотят :)
да уж ефчик - неужто так трудно галочку поставить - ридонли для чего то там :(
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38880316
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProЕсли я изначально сделаю проекцию - это будет оптимально для работы с БД, но тогда мне придется перестраивать проекции всякий раз, когда я модернизирую сущность заказа.

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

Но за всё надо платить, естественно. Хотя разницы нет, если ты модернизируешь сущность заказа, это отразится во всех слоях. Когда возникает потребность сократить монотонный труд, можно написать кодогенерацию. В любом случае, офигенный профит тут в строгой типизиации, и в оптимальности запросов/данных.

Shocker.ProЗЫ: Дополнительный вопрос - в твоем примере с автомаппером - сработает ли оптимизация, и данные разных сущностей из БД будут получены одним запросом с join-ом?

Да, конечно. Автомаппер молодцом, пока проблем с ним небыло )
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887728
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В развитие темы проекций.

А как создать динамическую проекцию (чтобы EF ее нормально понял и оттранслировал)?

Надо мутить с деревьями выражений или копать в сторону динамически создаваемого типа через рефлексию? Или есть какой-то более простой способ?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887751
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProВ развитие темы проекций.

А как создать динамическую проекцию (чтобы EF ее нормально понял и оттранслировал)?

Надо мутить с деревьями выражений или копать в сторону динамически создаваемого типа через рефлексию? Или есть какой-то более простой способ?

В смысле, динамическую проекцию? Выбрать разные наборы полей по условию? Или как?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887768
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, как-то нечетко сформулировал. Пожалуй, что вопрос даже на два пересекающихся распадается:

1) Как в рантайме создать проекцию из произвольного набора полей. Например автомаппер с его Project().To() не знает заранее набор полей для проекции, он его формирует на основе созданной в рантайме карты динамически - как?

2) Select(n => new { ... })
какие конструкции можно подсовывать в EF вместо "new { ... }" или "new MyPOCO() {...}", чтобы EF составил плоскую проекцию и выбрал все одним запросом?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887840
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro1) Как в рантайме создать проекцию из произвольного набора полей. Например автомаппер с его Project().To() не знает заранее набор полей для проекции, он его формирует на основе созданной в рантайме карты динамически - как?

Произвольный набор полей, это что? Как раз таки Project().To() заранее знает набор полей, так как при компиляции тип определён, набор свойств типа известен, кроме того должен быть определён маппинг для типа.

Или ты имеешь в виду некий нетипизированный датасет?

Shocker.Pro2) Select(n => new { ... })
какие конструкции можно подсовывать в EF вместо "new { ... }" или "new MyPOCO() {...}", чтобы EF составил плоскую проекцию и выбрал все одним запросом?

либо new {}, либо new MyPOCO {}. Сам по себе EF плоскую проекцию не создаёт, а вот AutoMapper умеет, если придерживаться соглашений .

Или ты имеешь в виду нечто типа SELECT *, и получить набор полей, имеющихся в БД? Просто не понимаю, куда это должно замаппиться, типа анонимный класс, созданный динамически на основе полученного набора? Не уверен, что в этом есть смысл, а на деле не помню, чтобы кто-то такое поддерживал. Технически для подобного результата надо будет мутить с рефлекшеном и эмитить код.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887849
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttКак раз таки Project().To() заранее знает набор полей, так как при компиляции тип определёнПри компиляции известно, какой набор полей будет на выходе, но неизвестно, какие поля будут затребованы из БД.

Допустим я в DTO-классе прописал поле CreatorName, которое автомаппером будет преобразовано как свойство Name у навигационного свойства Creator. При этом карту преобразования он ведь составляет в рантайме. То есть именно в рантайме он должен сообщить EF-у, какие поля из объектов и навигационных свойств ему нужны. Вот этот механизм я и пытаюсь понять.

=======================

Я, в общем-то, хочу разобраться, как EF работает с проекцией, чтобы у себя обобщить некоторые вещи...

Вот представь, на чистом SQL - есть некоторая типичная выборка из нескольких таблиц. При этом, в большинстве случаев она нужна не сама по себе, а в составе более глобальной выборки. Я создаю под нее View. Далее, когда мне нужна какая-то конкретная выборка, я сделаю селект из нужной таблицы и джойню необходимую вьюшку (или несколько). Тем самым, во View я инкапсулирую повторный код.

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

То есть, к примеру, у меня есть базовый DTO класс, но, используя его для проекции, я хочу в конкретных случаях присоединить еще пару полей (из связанных таблиц в том числе) и при этом не городить ветвистые деревья DTO-классов.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887858
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro,

Прочитал ветку до конца, потом поднялся опять в начало - Вы что там программируете-то?
Нейронные сети с нечеткой логикой?

Что-то прочитать из контекста, что-то записать в контекст, но только то, что нужно, а то что не нужно - не надо, а если всё-таки - то уронить то, что уронится?

Чудно право.

-- Просто для страховки от ошибок в алгоритме.

Сказано вслух. И все обсуждают.

Алгоритмы надо проектировать без ошибок. Чай не в яваскрипте массивы лепим.
...
Рейтинг: 0 / 0
25 сообщений из 44, страница 1 из 2
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / EF: Защитить сущность от изменений
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]