powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / EF: Защитить сущность от изменений
44 сообщений из 44, показаны все 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
EF: Защитить сущность от изменений
    #38887868
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MonochromatiqueАлгоритмы надо проектировать без ошибокПо улице надо ходить и не спотыкаться. Кушать надо аккуратно и не подавиться. Спать надо ложиться вовремя. Спасибо за полезный совет.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887869
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro,

Объясните, что это за кейс, при котором данные могут случайно изменится?

Причем, нежелательным образом?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887871
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttShocker.Pro,

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

У отражения как бы другое значение. То, что ты описал - это проецирование, нет?
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887875
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MonochromatiquehVosttShocker.Pro,

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

У отражения как бы другое значение. То, что ты описал - это проецирование, нет?

Ты прав, я имел в виду проекцию.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887881
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProMonochromatiqueАлгоритмы надо проектировать без ошибокПо улице надо ходить и не спотыкаться. Кушать надо аккуратно и не подавиться. Спать надо ложиться вовремя. Спасибо за полезный совет.

Всё, что тут насоветовали от AsNoTracking до создания новых объектов - по сути сводится к одному - к уничтожению контекста.

Чисто логически - могут существовать две (условно) стратегии использования контекста:
1. Пытаться хранить один контекст как можно дольше.
2. Пытаться хранить один контекст как можно меньше.

И как я всегда считал - EF CF - подталкивает ко второму. Считал данные из базы - забудь про контекст. Надо записать - создал новый, записал объект - забыл про контекст.

А здешний люд, как мне порой кажется, строит приложения вокруг БД, как в 1С.

Сущность, которую вы изменяете на форме/методе/wherever - может уже давно не принадлежать к контекту, так как встретила на своем пути automapper какой-нибудь, или простую проекцию через select - и что? Гоняться с отладчиком по всему приложению, выясняя - где сущность выпала из контекста? Страсть то какая.



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

Вона оно как.


Так что вот вам полезный совет - выбирайте безопасную стратегию работы с контекстом, и записывайте только то, что нужно.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887883
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProДопустим я в DTO-классе прописал поле CreatorName, которое автомаппером будет преобразовано как свойство Name у навигационного свойства Creator. При этом карту преобразования он ведь составляет в рантайме. То есть именно в рантайме он должен сообщить EF-у, какие поля из объектов и навигационных свойств ему нужны. Вот этот механизм я и пытаюсь понять.

В рантайме, да. Но тип результата всё равно известен на этапе компиляции, даже если он анонимный.

На счёт того, как это реализовано, можно посмотреть в исходниках AutoMapper, как он строит дерево выражений. Учитывай ещё то, что AutoMapper использует конфигурацию, задаваемую в CreateMap (а именно, с помощью инструкции MapFrom).

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

По сути, разбирает дерево выражений, затем рисует запрос. Для определения набора полей, важен тип результата (анонимный, или POCO).

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

Вообще, иногда я и делаю такую вьюшку в БД, затем маплю её к POCO в EF, чтобы использовать в различных JOIN-ах и выборках. Самое частое, это оформленные в виде View, CTE запросы, которые ни LINQ, ни EF не поддерживают ни в каком виде.

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

Т.е. вместо наследования, комбинирование? Представляешь, как это можно выразить на C#? Я нет, ведь C# не поддерживает множественное наследования, а скомбинировать два типа, чтобы получить один с полями из обоих типов — это возможно только для интерфейсов, но EF работает с классами.

Shocker.ProТо есть, к примеру, у меня есть базовый DTO класс, но, используя его для проекции, я хочу в конкретных случаях присоединить еще пару полей (из связанных таблиц в том числе) и при этом не городить ветвистые деревья DTO-классов.

Счастья нет Но меня вполне устраивали наследования. Комбинировать кстати тоже можно, если принять тот факт, что проекции будут не совсем плоские, а содержать данные из нескольких подпроекций. Тоже гуд.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887884
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MonochromatiqueВсё, что тут насоветовали от AsNoTracking до создания новых объектов - по сути сводится к одному - к уничтожению контекста.

Если тебе нужны только данные, чтобы их сразу же, например, отдать клиенту, то контекст после отдачи данных просто тупо не нужен. В рамках веб это вполне уместно.

MonochromatiqueСущность, которую вы изменяете на форме/методе/wherever - может уже давно не принадлежать к контекту, так как встретила на своем пути automapper какой-нибудь, или простую проекцию через select - и что? Гоняться с отладчиком по всему приложению, выясняя - где сущность выпала из контекста? Страсть то какая.

На форме не меняется никакая сущность, а данные вью модели. Поэтому эти рассуждения не в кассу. Кого ты гонять с отладчиком собрался? ))
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887886
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttMonochromatiqueВсё, что тут насоветовали от AsNoTracking до создания новых объектов - по сути сводится к одному - к уничтожению контекста.

Если тебе нужны только данные, чтобы их сразу же, например, отдать клиенту, то контекст после отдачи данных просто тупо не нужен. В рамках веб это вполне уместно.


Это уместно в любых рамках, ибо в контексте DI любой модуль может считаться клиентом.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887887
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttНа форме не меняется никакая сущность, а данные вью модели. Поэтому эти рассуждения не в кассу. Кого ты гонять с отладчиком собрался? ))

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

А до вьюмодели еще дорасти надо. Для многих тут MVVM - однозначно читается как WPF-ная придурь.

А потом страхуемся exception-ами от ошибок в алгоритмах.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887894
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И как же паттерн "репозиторий", мы же видим только его типа, ни о каком контексте мы не знаем, равно как и контексту, все "пришедшие" к нему на сохранение объекты - в диковинку.

Отсюда мАраль - контекст тречит изменения только в процедуре сохранения репозитория.

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

Это слишком абстрактно.

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

Чтобы не заставлять прикладного программиста постоянно зырить в стеклянный шар и гадать на кофейной гуще, не отдавай ему экземпляры модели EF. Используй DTO и проекции. Тогда и страховка будет 100%.

MonochromatiqueА до вьюмодели еще дорасти надо. Для многих тут MVVM - однозначно читается как WPF-ная придурь.

Так а чо там расти, элементарный же паттерн.

MonochromatiqueИ как же паттерн "репозиторий", мы же видим только его типа, ни о каком контексте мы не знаем, равно как и контексту, все "пришедшие" к нему на сохранение объекты - в диковинку.

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

MonochromatiqueДругие сценарии его (контекста) использования - нестабильны и опасны.

Любой универсальный совет вреден )) Даже микроскопом можно гвоздь забить, если до ближайшего магазина с молотками тыщи километров, а забить надо прямо сейчас.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38887906
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttЧтобы не заставлять прикладного программиста постоянно зырить в стеклянный шар и гадать на кофейной гуще, не отдавай ему экземпляры модели EF. Используй DTO и проекции. Тогда и страховка будет 100%.

С уничтожением контекста модели EF автоматически превращаются в... Ну ты в курсе.)))

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

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

Вот тут как раз и не очень понятно. Как я понимаю, EF при материализации запроса начинает анализировать дерево выражений, (n => new { k = n.Id }) он поймет и преобразует в нужную выборку, потому что она в пределах допустимого для IQueryable. (n => new { k = n.Id.MyMethod() }) не поймет, он не знает, как преобразовать MyMethod() в SQL, такую выборку я могу делать только на материализованной коллекции. Таким образом, выборка из БД зависит не только от выходного типа, но и от того, от правой части присваивания.

Автомаппер, в свою очередь, с SQL не работает, очевидно, это не его забота. Поэтому мне не очень понятно, что ты имеешь ввиду под "рисует запрос". Вполне возможно, это из-за того, что я не понимаю, какую роль в данном случае играет IQueryable.

hVosttВообще, иногда я и делаю такую вьюшку в БД, затем маплю её к POCO в EF, чтобы использовать в различных JOIN-ах и выборкахя правильно понял, что ты вынужден создавать навигационное свойство для цели такого джойна?

hVosttТ.е. вместо наследования, комбинирование? Представляешь, как это можно выразить на C#? Я нет, ведь C# не поддерживает множественное наследования, а скомбинировать два типа, чтобы получить один с полями из обоих типов — это возможно только для интерфейсов, но EF работает с классами.Гм, нет, пожалуй, я опять возвращаюсь к правой части присваивания. Я могу сделать такую проекцию "на лету":
(n => new { n, n.Creator.Organization.Name, n.Changer.Surname })
EF выберет сущность n целиком и еще два связанных поля. Так вот, я ищу способ, чтобы не расписывать каждый раз "n.Creator.Organization.Name, n.Changer.Surname" (допустим, это типовая выборка, допустим, там несколько полей) а каким-то образом использовать повторный код.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38888457
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProАвтомаппер, в свою очередь, с SQL не работает, очевидно, это не его забота. Поэтому мне не очень понятно, что ты имеешь ввиду под "рисует запрос". Вполне возможно, это из-за того, что я не понимаю, какую роль в данном случае играет IQueryable.

Автомаппер строит дерево выражений, основываясь на типе, соглашениях и конфигурации. А EF наоборот, парсит это дерево, преобразуя его в SQL. Набор полей в запросе зависит исключительно от типа возвращаемых данных в IQueryable<T>. IQueryable это «запрос» в мире .NET, и он содержит всю необходимую информацию для создания запроса SQL.

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

Shocker.Proя правильно понял, что ты вынужден создавать навигационное свойство для цели такого джойна?

Вовсе не обязательно. Хотя навигационные поля я делаю, но можно обойтись и без них, приджойнить, например по ID, EF прекрасно поймёт.


Shocker.ProГм, нет, пожалуй, я опять возвращаюсь к правой части присваивания. Я могу сделать такую проекцию "на лету":
(n => new { n, n.Creator.Organization.Name, n.Changer.Surname })
EF выберет сущность n целиком и еще два связанных поля. Так вот, я ищу способ, чтобы не расписывать каждый раз "n.Creator.Organization.Name, n.Changer.Surname" (допустим, это типовая выборка, допустим, там несколько полей) а каким-то образом использовать повторный код.

К сожалению нельзя совмещать отражения Автомаппера и отражения, создаваемые вручную анонимными типами. Т.е. Project().To() не совместимо с Select(p => new {...}). Т.е. либо создаешь все отражения в конфигурации Автомаппера, либо выбираешь все поля буквально по свойствам вручную. Я просто не встречал такого и не имел подобного опыта. Поэтому использую в основном чисто проекции автомаппера (который, кстати, прекрасно понимает вложенные проекции), либо реже проекции через анонимный тип (new { ... }), в зависимости от ситуации.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38888494
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt, спасибо, в целом понятно



MonochromatiqueИ как я всегда считал - EF CF - подталкивает ко второму. Считал данные из базы - забудь про контекст. Надо записать - создал новый, записал объект - забыл про контекст.

А здешний люд, как мне порой кажется, строит приложения вокруг БД, как в 1С.

Сущность, которую вы изменяете на форме/методе/wherever - может уже давно не принадлежать к контекту, так как встретила на своем пути automapper какой-нибудь, или простую проекцию через select - и что? Гоняться с отладчиком по всему приложению, выясняя - где сущность выпала из контекста? Страсть то какая.

Мне казалось - что это как бы само собой разумеющиеся вещи, и недоумевал, когда мне "втирали" про прокси объекты, долгоживущие контексты и прочее.
Так что вот вам полезный совет - выбирайте безопасную стратегию работы с контекстом, и записывайте только то, что нужно.С учетом того, что я (сейчас) работаю над Web, контекст у меня живет недолго )

Если пришел запрос на обновление сущности, я запрашиваю у EF сущность, обновляю ее и сохраняю изменения в контексте. Однако, при обновлении могут быть дернуты другие сущности, как для проверки правильности пришедших с клиента идентификаторов, так и для формирования вывода по результатам сохранения сущности. Они заведомо изменяться не должны, и я хочу их по умолчанию запрашивать только для чтения, о чем и был изначальный вопрос. Это - такой же предохранитель как private/protectet/abstract/internal/{ get; private set; }, как констрейнты в БД и т.п. - не дают сделать заведомо неверный шаг.

Посылы Хвоста насчет проекций, тем не менее, сыграли свою роль, это позволяет уменьшить количество слоев, на которые проникает сущность уровня EF. Но, для заведомо ReadOnly сущностей, которые все же необходимо получить целиком, AsNoTracking совершенно не мешает (так как реализован непосредственно в методе получения сущности, у которого есть необязательный параметр ,bool readOnly=true, что позволяет получить сущность для записи только указав это явно), соответственно при этом снижается нагрузка на сервер за счет неотслеживаемых сущностей.
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38894529
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttShocker.ProЗЫ: Дополнительный вопрос - в твоем примере с автомаппером - сработает ли оптимизация, и данные разных сущностей из БД будут получены одним запросом с join-ом?

Да, конечно. Автомаппер молодцом, пока проблем с ним небыло )
Прикольно, тут Автомаппер перестарался, похоже

Попытался добыть одним взмахом руки саму сущность и связанный с ней список в одно из свойств DTO
Код: c#
1.
2.
        CreateMap<MyEntityType, MyDTOType>()
          .ForMember(n => n.FooList, m => m.MapFrom(k => k.Foos.Select(n => n.Name).ToList()));

Получилось все одним запросом, вместо двух, то есть сама сущность была выбрана столько раз, сколько оказалось элементов в Foos

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

Используй groupBy

Код: c#
1.
tableRows.groupBy(row=>row.order).select(grouped_rows=> new DTO(){order = grouped_rows.Key,rows = grouped_rows.ToList()})
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38895261
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MonochromatiqueСмысл же Code First не только в "как-круто-создать-БД-кодом".
в этой хрени смысла мало

для хелловорд предназначена
...
Рейтинг: 0 / 0
EF: Защитить сущность от изменений
    #38895297
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилMonochromatiqueСмысл же Code First не только в "как-круто-создать-БД-кодом".
в этой хрени смысла мало

для хелловорд предназначена

O_O

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


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