【问题标题】:An elegant way to check if any items which has the same childrens exist一种检查是否存在具有相同子项的项目的优雅方法
【发布时间】:2013-08-09 15:37:26
【问题描述】:

我有这个项目:

public partial class PACK
{
    public int PACK_IDE { get; set; }
    public string PACK_DESCR { get; set; }
    public Nullable<System.DateTime> PACK_DATE_CREATED { get; set; }
    public Nullable<System.DateTime> PACK_DATE_MODIFIED { get; set; }
    public Nullable<System.DateTime> PACK_DATE_LAST_CALC { get; set; }
    public decimal PACK_COST { get; set; }
    public int PACK_QTY_POSS { get; set; }
    public string PACK_NOTE { get; set; }
    public int PACK_QTY_SOLD { get; set; }
    public decimal PACK_AVRG_SELL_PRICE { get; set; }
    public Nullable<int> PACK_DESTINATION { get; set; }

    public virtual ICollection<INVENTORY_PACK> INVENTORY_PACK { get; set; }
}

如您所见,其中包含一个库存包列表,形状如下:

public partial class INVENTORY_PACK
{
    public int INVENT_PACK_IDE { get; set; }
    public int INVENT_IDE { get; set; }
    public int PACK_IDE { get; set; }
    public int QTY { get; set; }

    public virtual INVENTORY INVENTORY { get; set; }
    public virtual PACK PACK { get; set; }
}

最后是 Inventory Items,它有 2 个目前很重要的字段:

public partial class INVENTORY
{
    public int INVENT_IDE { get; set; }
    public Nullable<int> CARD_IDE { get; set; }
    public Nullable<int> INVENT_NB_IN_STOCK { get; set; }
    public Nullable<int> INVENT_NB_QT_SOLD { get; set; }
    public string INVENT_ITEM_STATE { get; set; }

    public virtual CARD CARD { get; set; }
    public virtual ICollection<INVENTORY_PACK> INVENTORY_PACK { get; set; }
}

当我实际保存或创建一个新包时,我需要根据INVENT_ITEM_STATECARD_IDE 以及QTY 找到一种方法来检查是否存在具有完全相同库存项目的实际包在INVENTORY_PACK。如果这三个值相同,那么我们可以考虑拥有相同的孩子。我基本上需要搜索与我现在拥有的相同的任何包(使用 Linq 或任何 Linq-To-Sql 调用),但我真的不知道该怎么做,除了大量令人兴奋的for/foreach 循环。

编辑

根据要求,这是我一直在尝试做的一个示例。

internal void CreatePack(PackInfo _pack)
{
    using (TransactionScope scope = TransactionUtils.CreateTransactionScope())
    {
        try
        {
            var packQry = from pa in mDb.PACK
                          select pa;

            if (!packQry.Any())
            {
                PACK packToAdd = DataConverter.PackInfoToPACKData(_pack);

                mDb.PACK.Add(packToAdd);

                mDb.SaveChanges();

                int packID = mDb.PACK.Max(_x => _x.PACK_IDE);

                foreach (INVENTORY_PACK inventoryPack in packToAdd.INVENTORY_PACK)
                {
                    inventoryPack.PACK_IDE = packID;

                    mDb.SaveChanges();
                }
            }
            else
            {
                List<PACK> listPacks = new List<PACK>();

                foreach (var inventoryPackInfo in _pack.mListInventoryPackInPack)
                {
                    packQry = from pa in mDb.PACK
                              where pa.INVENTORY_PACK.Any(_item =>
                                      _item.INVENTORY.INVENT_IDE ==
                                      inventoryPackInfo.mInventoryItem.mInventoryID)
                              where pa.INVENTORY_PACK.Any(
                                      _item =>
                                      _item.INVENTORY.INVENT_ITEM_STATE ==
                                      inventoryPackInfo.mInventoryItem.mItemState)
                              where pa.INVENTORY_PACK.Any(_item => _item.QTY == inventoryPackInfo.mQuantity)
                              select pa;

                    if (packQry.Any())
                    {
                        listPacks.AddRange(packQry);
                    }
                }

                if (_pack.mListInventoryPackInPack.Count == 1)
                {

                }

                IDictionary<PACK, int> counts = new Dictionary<PACK, int>();

                foreach (var pack in listPacks)
                {
                    if (!counts.ContainsKey(pack))
                    {
                        counts.Add(pack, 1);
                    }
                    else
                    {
                        counts[pack]++;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }

        scope.Complete();
    }
}

示例

我认为我需要澄清我的需求。这是一个例子。

假设我有 1 个 PACK 包含 2 个 INVENTORY_PACK:1 是 INVENTORY 项目,INVENT_IDE 1234,CARD_IDE 4321,QTY 是 1,INVENT_ITEM_STATEPERFECT。第二个对象是INVENT_IDE4567,CARD_IDE7654,QTY是2和INVENT_ITEM_STATEPERFECT

我需要检查包以查看是否已经有一个包包含恰好所选参数中有两个项目。所以有很多可能性:

  • 如果我们有另一个现有的 PACK 具有相同的项目和相同的项目数量(在本例中为 2)、数量和 IDS,我们有一个完美匹配,我们认为PACK 已经存在;
  • 如果有一个 PACK 包含相同的物品,但还有另一个(本例中为 3 件或更多),它是否被视为 另一个包;那么我们没有匹配;
  • 如果任何包裹中只有其中一项,我们没有匹配项。

【问题讨论】:

  • 你能贴一些你试过的代码吗?
  • 我会深入研究并尝试给你一些结果,但我对如何比较 2 个对象感到非常困惑,所以我真的不确定比较 2 个对象列表:|
  • 依我的拙见,在没有提供理由的情况下标记问题的用户没有帮助。
  • 您是否正在尝试确定新PACK 对象集合中的每个INVENTORY_PACK 是否与其他对象匹配?我的意思是这三个值在INVENTORY_PACK 集合的每个 实例中是否必须相同?
  • 我正在尝试查找是否所有 INVENTORY_PACK 项目都在另一个 PACK 中完全找到。我想我可以举个例子。我会更新我的帖子。

标签: c# linq-to-sql


【解决方案1】:

如果我理解得很好,您可以执行以下操作:

实现两个 EqualityComparer(可以在您的业务层中实现,因为它只是业务逻辑)

class PACK_Comparer : EqualityComparer<PACK>
{
    public override bool Equals(PACK p1, PACK p2)
    {
        // Two PACK are Equals if their INVENTORYs contains the same INVENTORY items
        return (p1.INVENTORY_PACK.Count() == p2.INVENTORY_PACK.Count()
            && p1.INVENTORY_PACK.Intersect(p2.INVENTORY_PACK, new INVENTORY_PACK_Comparer()).Count() == p1.INVENTORY_PACK.Count());
    }
    public override int GetHashCode(PACK p)
    {
        // Ensure that if the Equals method returns true for two PACK p1 and p2
        // then the value returned by the GetHashCode method for p1 must equal the value returned for p2
        INVENTORY_PACK_Comparer comp = new INVENTORY_PACK_Comparer();
        int hCode = 0;
        foreach (var i in p.INVENTORY_PACK)
            hCode ^= comp.GetHashCode(i);
        return hCode.GetHashCode();
    }
}

class INVENTORY_PACK_Comparer : EqualityComparer<INVENTORY_PACK>
{
    public override bool Equals(INVENTORY_PACK i1, INVENTORY_PACK i2)
    {
        // Two INVENTORY_PACK are Equals if their INVENT_ITEM_STATE, CARD_IDE and QTY are Equals
        return (i1.INVENTORY.INVENT_ITEM_STATE == i2.INVENTORY.INVENT_ITEM_STATE
            && i1.INVENTORY.CARD_IDE == i2.INVENTORY.CARD_IDE
            && i1.QTY == i2.QTY);
    }

    public override int GetHashCode(INVENTORY_PACK i)
    {
        // Ensure that if the Equals method returns true for two INVENTORY_PACK i1 and i2
        // then the value returned by the GetHashCode method for i1 must equal the value returned for i2
        int hCode = i.INVENTORY.INVENT_ITEM_STATE.GetHashCode()
            ^ i.INVENTORY.CARD_IDE.GetHashCode()
            ^ i.QTY.GetHashCode();
        return hCode.GetHashCode();
    }
}

然后检查是否已经存在同一个PACK短到

bool exist = mDb.PACK.Contains(_pack, new PACK_Comparer());

如果您想获取 mDb 中已经存在的实际 PACK:

PACK_Comparer comp = new PACK_Comparer();
PACK existingPack = mDb.PACK.FirstOrDefault(p => comp.Equals(p, _pack));

请注意,我删除了“测试为空”的内容以使其更简单。 您需要自行实施。

问候, 杰拉德

【讨论】:

  • Az Za(在我的帖子上发表的评论)有一点:我不能使用这种方法(这似乎很有希望),因为我正在使用实体框架。这样做时出现以下错误:LINQ to Entities does not recognize the method 'Boolean Contains[PACK](System.Linq.IQueryable``1[MvcMagicAdmin.Models.DAL.Entities.PACK], MvcMagicAdmin.Models.DAL.Entities.PACK, System.Collections.Generic.IEqualityComparer``1[MvcMagicAdmin.Models.DAL.Entities.PACK])' method, and this method cannot be translated into a store expression.
  • 虽然崩溃仍然存在,但我已经根据您的解决方案进行了折衷,并且效果很好。谢谢!
  • 好!我很高兴看到你解决了它。我经历过类似的情况;我发现的技巧不是使用“包含”,而是使用实体的本地副本,然后使用“Where.(entity => entity.Contains(_pack, PackComparer))”
【解决方案2】:

这可能就是你想要的

int count = (from p in _pack.INVENTORY_PACK
            where pack.INVENTORY.INVENT_ITEM_STATE == p.INVENTORY.INVENT_ITEM_STATE
            select p).Count();

之后检查if(pack.QTY == count)

【讨论】:

  • 嗯,这将允许我检查任何具有相同数量项目的包,你说得对。但是如何分别比较每个项目以确保包中的项目与我尝试保存/创建的项目相同?
  • 而且我的任何物品都不共享相同的INVENT_ITEM_STATE,这也可以让我结帐吗?我不确定
  • 你必须通过编写一堆 if & else 循环来处理它们
  • 我已经更新了上面的代码,因为我一直在尝试,你可以看看周围
  • 如果值被填充,请尝试调试每个步骤。因为您的对象有点复杂和复杂,如果不调试就很难编写工作代码。
猜你喜欢
  • 2011-11-21
  • 2013-09-07
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
相关资源
最近更新 更多