a lot of people can't deal with updating entities "automatically" - I mean by rewriting each value separately.
Imagine following situation: we have a WCF service where client receives an Order entity via WCF means, and then changes some of the properties, then sends it back via WCF. To update such object normally we need to rewrite each of the properties manually, and I don't want to write separate code for every class (and rewrite it when properties change, for example) I have tried Linq2SQLEntityBase but somehow I can't get it to work, even though I studied the example thoroughly. So here is my proposition:
public class Alterator<TEntity,TDataContext>
where TDataContext : DataContext, new()
{
/// <summary>
/// Updates a group of entities, performing an atomic operation for each of them (the lambda is executed for each entity separately).
/// </summary>
/// <param name="newOrModifiedEntity">Any kind of IEnumerable of entities to insert or update.</param>
/// <param name="findOriginalLambda">A lambda expression that should return an original TEntity if the entity is to be updated or null if it is new.</param>
public static void AlterAll(IEnumerable<TEntity> entities, Func<TDataContext,TEntity> findOriginalLambda)
{
foreach (TEntity newEntity in entities) {
//a new DataContext initialization is required for this function to work correctly
using (TDataContext dataContext = new TDataContext())
{
dataContext.DeferredLoadingEnabled = false;
Type entityType = typeof(TEntity);
ITable tab = dataContext.GetTable(entityType);
TEntity originalEntity = findOriginalLambda(dataContext);
//if the lambda returned no matching existing record in database, create a new one. No need to if-check for existence before as long as your lambda is properly built
//(I suggest using SingleOrDefault() or FirstOrDefault() in queries).
if (originalEntity == null)
tab.InsertOnSubmit(newEntity);
else
{
开发者_高级运维 foreach (PropertyInfo p in entityType.GetProperties().Where(k => k.CanWrite))
{
var c = p.GetValue(newEntity, null);
var n = p.GetValue(originalEntity, null);
if (c != null && n != null && !c.Equals(n))
p.SetValue(originalEntity, c, null);
}
dataContext.SubmitChanges();
}
}
}
}
/// <summary>
/// Updates a single entity if the lambda expression returns a valid original entity. Inserts one if lambda returns null.
/// </summary>
/// <param name="newOrModifiedEntity">Entity to update or insert.</param>
/// <param name="findOriginalLambda">A lambda expression that should return an original TEntity if the entity is to be updated or null if it is new.</param>
public static void Alter(TEntity newOrModifiedEntity, Func<TDataContext, TEntity> findOriginalLambda) {
AlterAll(new TEntity[] { newOrModifiedEntity }, findOriginalLambda);
}
}
And an update code sample. It finds an order based on its key - OrderItemID. If null is returned, a new entry will be created.
public void AlterOrderItem(OrderItem o) {
Alterator<OrderItem, JDataContext>.Alter(o, t => t.OrderItems.Where(k => k.OrderItemID == o.OrderItemID).SingleOrDefault());
}
Is there a better way to do this? I've been trying over a week now.
I suggest taking a look at West Wind Business Framework at west wind
or download
Its a business object wrapper that makes life easier
Look at attaching entities, after you have returned an object from your service, when the client updates and returns the object, in the WCF service you can simply attach the object to the data context and then save the changes.
精彩评论