这是一种优雅的方式来检查是否存在具有相同子项的物品

本文关键字:存在 是否 检查 一种 方式 | 更新日期: 2023-09-27 18:27:07

我有这个项目:

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; }
}

最后,库存项目,它有两个重要的字段,现在很重要:

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以及INVENTORY_PACK中的QTY具有完全相同的库存项。如果这三个值相同,那么我们可以考虑生同样的孩子。我基本上需要搜索任何包(使用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个包含2个INVENTORY_PACKPACK:1是INVENTORY项,其中INVENT_IDE 1234,CARD_IDE 4321,QTY是1,而INVENT_ITEM_STATEPERFECT。第二个对象是INVENT_IDE 4567、CARD_IDE 7654、QTY是2和INVENT_ITEM_STATE PERFECT

我需要检查包,看看是否已经有一个包包含,确切地说在所选参数中有两个项目。所以有很多可能性:

  • 如果我们有另一个现有的PACK,它具有相同的项目和相同数量的项目(在本例中为2)、数量和IDS,则我们有一个完全匹配,并且我们认为PACK已经存在
  • 如果有一个PACK包含相同的项目,但有另一个项目(本例为3个或更多项目),是否认为是另一个包;那么我们就没有对手了
  • 如果任何包裹只有其中一项,则我们没有匹配项

这是一种优雅的方式来检查是否存在具有相同子项的物品

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

实现两个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));

请注意,我删除了"测试为空"的内容以使其更简单。您需要自己实现这一点。

谨致问候,Gerard

这可能就是您想要的

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) 之后