Один из вариантов - это то, что вы сказали сделать запрос без отслеживания.
ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First(c => c.ID == 232);
Затем клиент может изменить 'customer'
, как требуется в памяти, и в контексте ничего не происходит.
Теперь, когда вы действительно хотите внести изменения, вы можете сделать это:
// get the value from the database
var original = ctx.Customers.First(c => c.ID == customer.ID);
// copy values from the changed entity onto the original.
ctx.ApplyPropertyChanges(customer); .
ctx.SaveChanges();
Теперь, если вас не устраивает запрос по причинам производительности или параллелизма, вы можете добавить новый метод расширения AttachAsModified (...) в ObjectContext.
это выглядит примерно так:
public static void AttachAsModified<T>(
this ObjectContext ctx,
string entitySet,
T entity)
{
ctx.AttachTo(entitySet, entity);
ObjectStateEntry entry =
ctx.ObjectStateManager.GetObjectStateEntry(entity);
// get all the property names
var propertyNames =
from s in entry.CurrentValues.DataRecordInfo.FieldMetadata
select s.FieldType.Name;
// mark every property as modified
foreach(var propertyName in propertyNames)
{
entry.SetModifiedProperty(propertyName);
}
}
Теперь вы можете написать такой код:
ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First();
// make changes to the customer in the form
ctx.AttachAsModified("Customers", customer);
ctx.SaveChanges();
А теперь у вас нет параллелизма или посторонних запросов.
Единственная проблема сейчас связана со свойствами FK. Вам, вероятно, стоит взглянуть на мой список советов о помощи: http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx
Надеюсь, это поможет
Alex