2013-09-08 4 views
0

В моих проектах у меня часто нет отдельного уровня доступа к данным, но мне нравится добавлять некоторые исходные SQL-методы в мои объекты по соображениям производительности.Получить DbContext внутри Entity

Итак, у меня есть MassUpdateSomethingAndPersist() в одном из моих классов Entity. Для массового обновления мне нужно позвонить dbContext.Database.ExecuteSqlCommand изнутри Entity. Но, конечно, мне нужна ссылка на DbContext.

Вопрос

Можно ли получить DbContext внутри Сущности? Использование размышлений для этого не является проблемой для меня, потому что это относительно тяжелые операции в любом случае.

ответ

3

Я думаю, что вы пытаетесь сделать, указывает на недостаток дизайна OO. Не должно быть ответственности классов Entity для обновления базы данных. Это несет ответственность за DBContext.

Так

  1. Нет, это невозможно, и
  2. Хотеть, чтобы сделать это, указует на конструктивный недостаток (возможно)

Если вы хотите выполнить пользовательский SQL, вы должны выполнить его от вызывающего, в контексте, а не из самого объекта.

Пример можно найти здесь: DBContext Native SQL Queries.

+1

У вас есть хороший источник, который может объяснить мне, почему это такая плохая практика (для средних проектов) - до тех пор, пока этот метод не будет понятен этой базе данных? Просто работа с Entities притворяется, что за ней нет (медленных) операций с базой данных, что оказалось неэффективным для моих проектов. –

+0

Ну, это действительно хорошая практика OO. Ключевые слова: SRP, Разделение проблем, Принцип инверсии зависимостей. Ознакомьтесь с принципами SOLID (например, здесь: http://www.codeproject.com/Articles/60845/The-S-O-L-I-D-Object-Oriented-Programming-OOP-Prin). Ваше предположение по крайней мере нарушит принципы инверсии зависимостей и единой ответственности. –

+0

Да, я знаю ТВЕРДОЕ, но мне нравятся некоторые практические примеры. Как я уже сказал, притворяясь, что нет (медленных) операций с базой данных за Entities **, ** доказано, что не работает для моих проектов.Добавляя (хорошо названные) методы, которые выполняются в некоторых очень специфических случаях, необработанный SQL не оказался для меня проблемой ** еще **. Может быть, хорошая тема для другого вопроса :) –

1

Можно:

((IObjectContextAdapter)dbContext).ObjectContext.ObjectMaterialized += (sender, e) => 
{ 
    (e.Entity as IEntityWithDbContext).DbContext = dbContext; 
} 

public interface IEntityWithDbContext 
{ 
    public DbContext DbContext { get; set; } 
} 

public partial class User : IEntityWithDbContext 
{ 
    public IEntityWithDbContext.DbContext DbContext { get; set; } 
} 

Но это еще недостаток дизайна ...

Учитывая ваше описание, вы должны легко быть в состоянии сделать MassUpdateSomethingAndPersist() метод в DbContext (т.е. MassUpdateSomethingAndPersist(something)).

+0

Проблема в том, что, поскольку я работаю (видимо?) С относительными большими наборами данных, это то, что у меня довольно много таких методов. Добавление их всех в DbContext ** действительно ** противоречит принципу «единой ответственности», на мой взгляд. Создание отдельного класса для каждого объекта только для этих «массовых обновлений» кажется для меня большим количеством дополнительных накладных расходов, в то время как я действительно не вижу в нем решения каких-либо прямых проблем (пока понятно, что метод также сохраняется в базе данных). –

0

В Entity Framework вы должны следовать концепции Entd Domain Driven Design (DDD), которая заключается в том, что она всегда persistence ignorant. Если вы нарушите этот шаблон, как вы просите, тогда вам может быть очень сложно выполнить правильное модульное тестирование.

Шаблон, в котором объект изменяет свое собственное представление в базе данных, известен как the Active Record Pattern и не является чем-то, что рекомендуется для Entity Framework. Если вы хотите использовать шаблон активной записи, посмотрите на структуру, предназначенную для него - например, Castle ActiveRecord.

+0

Модульное тестирование довольно просто, если вы просто изменили два поля на Entity. Проблема в том, что в моем реальном приложении иногда мне нужно одновременно обновлять сотни свойств. Выполнение этого без SQL невозможно, поэтому пользователь кода не может работать «persistence ignorant» в любом случае. Большая часть моего кода по-прежнему остается ненаучной, но иногда мне действительно нужен MassUpdateAndPersist(). –

+0

Этот замок ActiveRecord выглядит интересным, хотя, поэтому я могу взглянуть, поможет ли это мне дальше. –

+0

Я не вижу, как количество полей имеет к этому какое-то отношение. Вы просто обновляете как можно больше своей сущности и передаете обновленную сущность для сохранения. Одно большое спасение будет более эффективным, чем сотни маленьких. –