|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
MonochromatiqueАлгоритмы надо проектировать без ошибокПо улице надо ходить и не спотыкаться. Кушать надо аккуратно и не подавиться. Спать надо ложиться вовремя. Спасибо за полезный совет. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:01 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
Shocker.Pro, Объясните, что это за кейс, при котором данные могут случайно изменится? Причем, нежелательным образом? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:03 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
hVosttShocker.Pro, Рекомендую забыть про AsNoTracking. Чтобы получать сущности только для чтения, просто воспользуйся отражением, и будет счастье: У отражения как бы другое значение. То, что ты описал - это проецирование, нет? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:07 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
MonochromatiquehVosttShocker.Pro, Рекомендую забыть про AsNoTracking. Чтобы получать сущности только для чтения, просто воспользуйся отражением, и будет счастье: У отражения как бы другое значение. То, что ты описал - это проецирование, нет? Ты прав, я имел в виду проекцию. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:14 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
Shocker.ProMonochromatiqueАлгоритмы надо проектировать без ошибокПо улице надо ходить и не спотыкаться. Кушать надо аккуратно и не подавиться. Спать надо ложиться вовремя. Спасибо за полезный совет. Всё, что тут насоветовали от AsNoTracking до создания новых объектов - по сути сводится к одному - к уничтожению контекста. Чисто логически - могут существовать две (условно) стратегии использования контекста: 1. Пытаться хранить один контекст как можно дольше. 2. Пытаться хранить один контекст как можно меньше. И как я всегда считал - EF CF - подталкивает ко второму. Считал данные из базы - забудь про контекст. Надо записать - создал новый, записал объект - забыл про контекст. А здешний люд, как мне порой кажется, строит приложения вокруг БД, как в 1С. Сущность, которую вы изменяете на форме/методе/wherever - может уже давно не принадлежать к контекту, так как встретила на своем пути automapper какой-нибудь, или простую проекцию через select - и что? Гоняться с отладчиком по всему приложению, выясняя - где сущность выпала из контекста? Страсть то какая. Мне казалось - что это как бы само собой разумеющиеся вещи, и недоумевал, когда мне "втирали" про прокси объекты, долгоживущие контексты и прочее. Вона оно как. Так что вот вам полезный совет - выбирайте безопасную стратегию работы с контекстом, и записывайте только то, что нужно. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:21 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
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-классов. Счастья нет Но меня вполне устраивали наследования. Комбинировать кстати тоже можно, если принять тот факт, что проекции будут не совсем плоские, а содержать данные из нескольких подпроекций. Тоже гуд. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:24 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
MonochromatiqueВсё, что тут насоветовали от AsNoTracking до создания новых объектов - по сути сводится к одному - к уничтожению контекста. Если тебе нужны только данные, чтобы их сразу же, например, отдать клиенту, то контекст после отдачи данных просто тупо не нужен. В рамках веб это вполне уместно. MonochromatiqueСущность, которую вы изменяете на форме/методе/wherever - может уже давно не принадлежать к контекту, так как встретила на своем пути automapper какой-нибудь, или простую проекцию через select - и что? Гоняться с отладчиком по всему приложению, выясняя - где сущность выпала из контекста? Страсть то какая. На форме не меняется никакая сущность, а данные вью модели. Поэтому эти рассуждения не в кассу. Кого ты гонять с отладчиком собрался? )) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:29 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
hVosttMonochromatiqueВсё, что тут насоветовали от AsNoTracking до создания новых объектов - по сути сводится к одному - к уничтожению контекста. Если тебе нужны только данные, чтобы их сразу же, например, отдать клиенту, то контекст после отдачи данных просто тупо не нужен. В рамках веб это вполне уместно. Это уместно в любых рамках, ибо в контексте DI любой модуль может считаться клиентом. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:32 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
hVosttНа форме не меняется никакая сущность, а данные вью модели. Поэтому эти рассуждения не в кассу. Кого ты гонять с отладчиком собрался? )) Никакой разницы - на форме или еще где-то. Никто не застрахован от того, что в какой-то момент ты думаешь, что сущность тречится контекстом, а она уже тю-тю. А до вьюмодели еще дорасти надо. Для многих тут MVVM - однозначно читается как WPF-ная придурь. А потом страхуемся exception-ами от ошибок в алгоритмах. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:36 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
И как же паттерн "репозиторий", мы же видим только его типа, ни о каком контексте мы не знаем, равно как и контексту, все "пришедшие" к нему на сохранение объекты - в диковинку. Отсюда мАраль - контекст тречит изменения только в процедуре сохранения репозитория. Другие сценарии его (контекста) использования - нестабильны и опасны. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:44 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
MonochromatiqueЭто уместно в любых рамках, ибо в контексте DI любой модуль может считаться клиентом. Это слишком абстрактно. MonochromatiqueНикакой разницы - на форме или еще где-то. Никто не застрахован от того, что в какой-то момент ты думаешь, что сущность тречится контекстом, а она уже тю-тю. Чтобы не заставлять прикладного программиста постоянно зырить в стеклянный шар и гадать на кофейной гуще, не отдавай ему экземпляры модели EF. Используй DTO и проекции. Тогда и страховка будет 100%. MonochromatiqueА до вьюмодели еще дорасти надо. Для многих тут MVVM - однозначно читается как WPF-ная придурь. Так а чо там расти, элементарный же паттерн. MonochromatiqueИ как же паттерн "репозиторий", мы же видим только его типа, ни о каком контексте мы не знаем, равно как и контексту, все "пришедшие" к нему на сохранение объекты - в диковинку. Ну почему же, говорю же у любой абстракции есть пределы, надо понимать, что там за бортом плещется контекст, а глубже вообще реляционная БД, или даже не реляционная, чо уж там )) Да, мы пытаемся обстрагироваться как бы, репа скрывает реализацию, но это как с оружием: военным требуется знать как устроено оружие, принципы его действия и даже конструкция, даже если они по идее должны только жать на гашетку. MonochromatiqueДругие сценарии его (контекста) использования - нестабильны и опасны. Любой универсальный совет вреден )) Даже микроскопом можно гвоздь забить, если до ближайшего магазина с молотками тыщи километров, а забить надо прямо сейчас. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 01:55 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
hVosttЧтобы не заставлять прикладного программиста постоянно зырить в стеклянный шар и гадать на кофейной гуще, не отдавай ему экземпляры модели EF. Используй DTO и проекции. Тогда и страховка будет 100%. С уничтожением контекста модели EF автоматически превращаются в... Ну ты в курсе.))) Смысл же Code First не только в "как-круто-создать-БД-кодом". ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 02:09 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
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" (допустим, это типовая выборка, допустим, там несколько полей) а каким-то образом использовать повторный код. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 11:10 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
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 { ... }), в зависимости от ситуации. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 14:06 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
hVostt, спасибо, в целом понятно MonochromatiqueИ как я всегда считал - EF CF - подталкивает ко второму. Считал данные из базы - забудь про контекст. Надо записать - создал новый, записал объект - забыл про контекст. А здешний люд, как мне порой кажется, строит приложения вокруг БД, как в 1С. Сущность, которую вы изменяете на форме/методе/wherever - может уже давно не принадлежать к контекту, так как встретила на своем пути automapper какой-нибудь, или простую проекцию через select - и что? Гоняться с отладчиком по всему приложению, выясняя - где сущность выпала из контекста? Страсть то какая. Мне казалось - что это как бы само собой разумеющиеся вещи, и недоумевал, когда мне "втирали" про прокси объекты, долгоживущие контексты и прочее. Так что вот вам полезный совет - выбирайте безопасную стратегию работы с контекстом, и записывайте только то, что нужно.С учетом того, что я (сейчас) работаю над Web, контекст у меня живет недолго ) Если пришел запрос на обновление сущности, я запрашиваю у EF сущность, обновляю ее и сохраняю изменения в контексте. Однако, при обновлении могут быть дернуты другие сущности, как для проверки правильности пришедших с клиента идентификаторов, так и для формирования вывода по результатам сохранения сущности. Они заведомо изменяться не должны, и я хочу их по умолчанию запрашивать только для чтения, о чем и был изначальный вопрос. Это - такой же предохранитель как private/protectet/abstract/internal/{ get; private set; }, как констрейнты в БД и т.п. - не дают сделать заведомо неверный шаг. Посылы Хвоста насчет проекций, тем не менее, сыграли свою роль, это позволяет уменьшить количество слоев, на которые проникает сущность уровня EF. Но, для заведомо ReadOnly сущностей, которые все же необходимо получить целиком, AsNoTracking совершенно не мешает (так как реализован непосредственно в методе получения сущности, у которого есть необязательный параметр ,bool readOnly=true, что позволяет получить сущность для записи только указав это явно), соответственно при этом снижается нагрузка на сервер за счет неотслеживаемых сущностей. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2015, 14:26 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
hVosttShocker.ProЗЫ: Дополнительный вопрос - в твоем примере с автомаппером - сработает ли оптимизация, и данные разных сущностей из БД будут получены одним запросом с join-ом? Да, конечно. Автомаппер молодцом, пока проблем с ним небыло ) Прикольно, тут Автомаппер перестарался, похоже Попытался добыть одним взмахом руки саму сущность и связанный с ней список в одно из свойств DTO Код: c# 1. 2.
Получилось все одним запросом, вместо двух, то есть сама сущность была выбрана столько раз, сколько оказалось элементов в Foos Не, ну конечно, можно и два запроса сделать, хотел покрасивее и пообобщеннее, может ты вдруг ты знаешь приемчик? )) ... |
|||
:
Нравится:
Не нравится:
|
|||
04.03.2015, 13:24 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
Shocker.Pro, Используй groupBy Код: c# 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
04.03.2015, 23:03 |
|
EF: Защитить сущность от изменений
|
|||
---|---|---|---|
#18+
MonochromatiqueСмысл же Code First не только в "как-круто-создать-БД-кодом". в этой хрени смысла мало для хелловорд предназначена ... |
|||
:
Нравится:
Не нравится:
|
|||
04.03.2015, 23:31 |
|
|
start [/forum/topic.php?fid=17&msg=38887894&tid=1349614]: |
0ms |
get settings: |
11ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
179ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
58ms |
get tp. blocked users: |
2ms |
others: | 17ms |
total: | 306ms |
0 / 0 |