原始列表与编辑的对象列表;如何使用linq找到已编辑的项目?

时间:2012-10-12 05:47:08

标签: c# linq list compare dto

我有一个实现IEquatable接口的OrderDto类。我有一个从数据库中检索为OrderDto对象的订单列表。此列表由最终用户编辑...添加新对象;删除现有对象;编辑现有对象。我需要确定以下内容:

  1. 列表中的新对象;
  2. 列表中已删除的对象;
  3. 列表中已编辑的对象;
  4. 我已经评论了以下代码来讨论这三个目标。前两个是微不足道的,但我列表中的第三个项目非常令人烦恼!我似乎无法使用linq创建它。我希望你能给我一个正确方向的推动。有关详细信息,请参阅以下代码。

    感谢您的帮助! 麦克

    // Get the original list of OrderDtos before the user did anything.
    var entityOrders = Mapper.Map<IList<OrderEntity>, IList<OrderDto>>(entity.Orders.ToList());  
    
    // dto.Orders is a parameter that is being used in this code.  It is the list of OrderDto
    // objects that the user has modified: Insert, edit, delete.
    
    // Works properly to locate items that were deleted.          
    var deletedOrders = entityOrders.Except(dto.Orders);
    
    // Works properly to locate items that were added.
    var addedOrders = dto.Orders.Except(entityOrders);
    
    // Determine the list of order objects less new orders in the list.
    // The user has already deleted objects, so we don't have to worry
    // about them.  This list will contain only items that MAY have 
    // been edited.
    var potentialChanges = dto.Orders.Except(addedOrders);
    
    // ARGGG!  I cannot seem to get this one to work properly!  As you can see in the 
    // definition of the OrderDto, it implements the IEquatable interface.  So, it 
    // should be very easy to determine which items in the dto.Orders list have been
    // edited as opposed to the original version in the entityOrders list.  What I 
    // would like to have is a list of all the OrderDto objects in the dto.Orders list
    // that have been modified.  Since OrderDto implements IEquatable, we should be able
    // to compare OrderDto objects directly, but I have not been able get it to work.
    // Please helP! :)
    var changedOrders =
       from dtoOrder in potentialChanges
       let entityOrder = entityOrders.First(x => x.OrderId == dtoOrder.OrderId)
       where entityOrder != null && !dtoOrder.Equals(entityOrder)
       select dtoOrder;
    

    以下是OrderDto类的定义......

    public class OrderDto : IEquatable<OrderDto>
    {
        public long OrderId { get; set; }
        public string DisplayAs { get; set; }
    
        #region IEquatable
        public override int GetHashCode()
        {
            // Populate with all fields so
            // we can detect when an entity
            // has been edited.
            return 
            (
                (int) OrderId ^ 
                DisplayAs.GetHashCode()
            );
    
        }
    
        public override bool Equals(object other)
        {
            return this.Equals(other as OrderDto);
        }
    
        public bool Equals(OrderDto other)
        {
            // Populate with all fields so
            // we can detect when an entity
            // has been edited.
            return 
            (
                other != null &&
                other.OrderId == this.OrderId &&
                other.DisplayAs == this.DisplayAs 
            );
        } 
    
        #endregion
    }
    

1 个答案:

答案 0 :(得分:0)

最简单的可能是包含State属性,例如值New, Saved, Loaded, Modified。您还可以添加IsDeleted属性。

然后,您实现每个属性集以抛出PropertyChanged事件,并实现一个自动将State属性设置为Modified的事件处理程序。

稍后您可以轻松查询:

var modified = entityOrders.Where(x => x.State == EntityState.Modified);

这种方法具有非常慎重的优点,即你是明确的,代码是可读的,而不是试图变得困难(并且写得太多而且代码太复杂)。

以同样的方式,您可以实现Delete()方法,该方法只是将实体标记为已删除, 并将所有已删除的实体查询为:

var deleted = entityOrders.Where(x => x.IsDeleted);

// ignore objects that were created, then deleted, without saving
var deleted = entityOrders.Where(x => x.IsDeleted && x.State != x.New); 

以及所有有效数据:

var data = entityOrders.Where(x => !x.IsDeleted);