C# 通过反射将LINQ更新为SQL-我的态度。寻求改进建议

C# 通过反射将LINQ更新为SQL-我的态度。寻求改进建议,c#,linq,entity,entities,C#,Linq,Entity,Entities,很多人无法处理自动更新实体的问题——我的意思是分别重写每个值 设想以下情况:我们有一个WCF服务,其中客户端通过WCF方式接收订单实体,然后更改一些属性,然后通过WCF将其发送回。要正常地更新这样的对象,我们需要手动重写每个属性,我不想为每个类编写单独的代码,并在属性更改时重写它,例如,我尝试了Linq2SQLEntityBase,但不知何故,我无法让它工作,尽管我已彻底研究了该示例。因此,我的建议如下: public class Alterator<TEntity,TDataContex

很多人无法处理自动更新实体的问题——我的意思是分别重写每个值

设想以下情况:我们有一个WCF服务,其中客户端通过WCF方式接收订单实体,然后更改一些属性,然后通过WCF将其发送回。要正常地更新这样的对象,我们需要手动重写每个属性,我不想为每个类编写单独的代码,并在属性更改时重写它,例如,我尝试了Linq2SQLEntityBase,但不知何故,我无法让它工作,尽管我已彻底研究了该示例。因此,我的建议如下:

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);
    }
}
和一个更新代码示例。它根据其键-OrderItemID查找订单。如果返回null,将创建一个新条目

 public void AlterOrderItem(OrderItem o) {
    Alterator<OrderItem, JDataContext>.Alter(o, t => t.OrderItems.Where(k => k.OrderItemID == o.OrderItemID).SingleOrDefault());
}

有更好的方法吗?我已经试了一个多星期了。

我建议在


它是一个业务对象包装器,使生活更轻松

查看实体,从服务返回对象后,当客户端更新并返回对象时,在WCF服务中,您只需将对象附加到数据上下文,然后保存更改。

但是如何分离实体?对不起,我编辑了我的帖子。您不必实际分离实体,只需返回它即可。一旦服务/客户端对其进行序列化/反序列化,它将不会保持连接状态。我已经尝试过此操作,但无法使其工作-出现重复密钥异常等等。使用了dataContext..AttachenEntity、originalEntity,然后是dataContext.RefreshMode.KeepCurrentValues,但这仅在连接模式中不涉及WCF时有效。你能给我提供一个工作代码段吗?对不起,我现在没有时间工作:-使用dataContext.Set.Attachentity。这都是假设您使用的是实体框架btw