2015-02-25 1 views
1

Я вижу что-то в Entity Framework, у меня есть мнение, что я либо полностью неправильно понимаю, как работает контекст базы данных, либо EF фактически нарушен (и я знаю, что, скорее всего, t получить его).Контекст структуры Entity, который не действует, как я ожидал

Рассмотрим следующий сценарий:

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

Тогда мы имеем что-то похожее на следующее:

public void SetAttendance(int dayId,int attendanceId, int attendanceId, String mark) 
{ 
    updateAttendance = new StudentAttendance() 
    { 
    Code=String.Empty, 
    AttendanceId=attendanceId, 
    DayId = dayId 
    }; 
    context.Attach(updateAttendance); 
//I don't save changes yet because I now need to do some logic 
var markedAttendanceCount = context.StudentAttendance.Where(att=> !String.IsNullOrEmpty(att.Code) && att.DayId == dayId).Count(); 

var allAttendanceCount = context.StudentAttendance.Where(att=> att.DayId == dayId).Count(); 

    var updateDay = new ClassDay() 
    { 
     DayId = dayId, 
     AllMarked = markedAttendanceCount = allAttendanceCount 
    }; 
    context.Attach(updateDay); 
    context.SaveChanges(); 
} 

Я бы ожидать, что если бы я называть этот метод SetAttendance следующим образом:

myworker.SetAttendance(10,20,String.Empty); 

, что он должен правильно понимать, что посещаемость ибо день не полностью отмечен. То, что я вместо этого вижу, - это то, что мой взгляд на запрос int на context.StudentAttendance запрашивает базу данных. Таким образом, мое обнаружение изменения статуса дня всегда одно.

Я думал, что контекст в основном должен быть достаточно умным, чтобы вы могли написать что-то вроде этого. По сути, у меня всегда складывалось впечатление, что контекст db позволяет существенно работать с сериализуемым видом транзакций. Когда вы вносите изменения в данные через свой контекст, эти изменения будут отражаться в запросах против контекста. Я что-то упускаю?

ответ

0

EF не работает таким образом, нет. По соображениям производительности в основном.

Однако context.StudentAttendance.Local предоставляет набор, содержащий добавленные объекты. Он также содержит любой объект, ранее загруженный контекстом в запросе. Если вам нравится, вы можете загрузить весь DbSet в память, как описано здесь: https://msdn.microsoft.com/en-au/data/jj592872.aspx, однако это не рекомендуется для больших наборов данных.

Кроме того, вы должны использовать context.Add(), а не context.Attach(). Последнее относится к сущностям, которые уже существуют в базе данных.

+0

Спасибо. В реальном коде я различаю и делаю контекст. Добавьте, если это новая метка, и добавьте, если я обновляю. Я попытался опустить пример, чтобы сделать то, что я просил более ясно. Я вижу, о чем вы говорите, и цените ответ. Мне нужно будет оценить, как я могу решить свою конкретную потребность в свете моего лучшего понимания сейчас :) – Danny

0

Это правда, что вы не совсем понимаете, как работает EF, но я думаю, что EF виноват в этом. Вы задаете очень хороший и правильный вопрос.

NHibernate, в отличие от EF, имеет этот AutoFlush feature. Это означает, что «в любой момент» он может вносить изменения в базу данных, чтобы синхронизировать локальные изменения и содержимое базы данных без участия разработчика. В вашем случае он сохранил новый StudentAttendance перед тем, как запросить существующие из базы данных. Так что если новый соответствует предикату (DayId == dayId), он внес бы вклад в allAttendanceCount. Эта функция, когда ее хорошо понимают, позволяет очень интуитивно понятный способ обработки данных точно так, как вы ожидали, что EF будет вести себя.

Правда, однако, что AutoFlush всегда ускользает от разработчиков, поэтому они часто просто отключили его. Как разработчик вы хотите иметь полный контроль, вы не хотите зависеть от какой-то умной функции, которая, кажется, имеет свою собственную жизнь. (Хотя реальность такова, что вы, вероятно, просто не нашли времени, чтобы полностью ее получить).

Я могу представить, что по этой причине команда EF решила не реализовывать такую ​​функцию.

А что делать в вашем случае? Не просто. Когда после добавления нового StudentAttendance вы бы сделали ...

context.StudentAttendance.Load(); 

(при условии, что у вас есть DbContext, хотя ваш «context.Attach», кажется, не быть в строке,).

А потом ...

var allAttendanceCount = context.StudentAttendance 
           .Local // <= Local! Includes the new item 
           .Where(att=> att.DayId == dayId) 
           .Count(); 

... вы бы желаемого результата. Но, конечно, загрузка всех записей StudentAttendance - это огромный перебор.

Одна простая альтернатива для счета, как и сейчас, и добавить 1 к ней.

Еще одна альтернатива - имитировать автозапуск, сортировать и сохранять новый StudentAttendance, прежде чем делать счет. Но тогда вам придется обернуть все в TransactionScope. Одно из преимуществ заключается в том, что у вас будет самое последнее значение allAttendanceCount.

Смежные вопросы