一种优雅的方式来检查是否存在任何具有相同子项的项目

时间:2013-08-09 15:37:26

标签: c# linq-to-sql

我有这个项目:

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的完全相同的库存项目,以及QTY中的INVENTORY_PACK。如果这三个值相同,那么我们可以考虑拥有相同的孩子。我基本上需要搜索任何Packs(使用Linq或任何Linq-To-Sql调用)哪个孩子与我现在拥有的相同,但我不知道如何做到这一点,除了大量的心灵 - 为/ 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是INVENTORYINVENT_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项或更多项目),则会将其视为另一个包;然后我们没有匹配;
  • 如果任何包只有这些项目中的一个,我们没有匹配。

2 个答案:

答案 0 :(得分: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));

请注意,我删除了'test is null'的内容,以简化它。 你需要自己实现这个。

此致 杰拉德

答案 1 :(得分:0)

这可能是你想要的

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)