【问题标题】:Original List vs Edited List of objects; How to locate the edited items with linq?原始列表与对象编辑列表;如何使用 linq 定位已编辑的项目?
【发布时间】:2012-10-12 05:47:07
【问题描述】:

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

  1. 列表中的新对象;
  2. 列表中的已删除对象;
  3. 列表中已编辑的对象;

我评论了以下代码来讨论这三个目标。前两项是微不足道的,但我列表中的第三项非常令人烦恼!我似乎无法使用 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
}

【问题讨论】:

  • 你能详细说明它是如何不起作用的吗? changedContent 最终包含什么?

标签: c# linq list compare dto


【解决方案1】:

最简单的方法可能是包含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); 

【讨论】:

  • 您好 Roy,我同意您的观点,您的解决方案很容易实现和理解,但是,唉,我们的应用程序架构不支持它。 :( 所以,我仍然需要确定已编辑项目的列表。我添加了一个新列表“potentialChanges”,这是用户在删除添加后创建的订单列表中剩下的内容。剩下的项目可能已被编辑。将 potentialChanges 列表中的对象与 entityOrders 列表进行比较将提供已更改的对象。希望我们可以修复我的 linq。再次感谢!:)
猜你喜欢
  • 1970-01-01
  • 2021-12-15
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多