检查数组是否包含在LINQ表达式中的数组数组中

本文关键字:数组 表达式 LINQ 是否 包含 检查 | 更新日期: 2025-01-25 10:49:13

我的单元测试有一些问题,它使用伪上下文(意味着没有数据库连接)。在生产环境中,它与sql连接,一切都很清楚。但是,在伪造上下文的情况下,发生了一些奇怪的事情——在数组"validCardItems"的数组中找不到数组"item.OfferKey"

//Array of arrays validCartItems values for example
byte[] offerKey1 = { 30, 163, 252, 225, 36, 208, 128, 47, 64, 244, 34, 199, 28, 57, 110, 215 };
byte[] offerKey2 = { 31, 163, 254, 225, 35, 203, 119, 47, 65, 244, 24, 199, 28, 56, 110, 215 };
byte[][] validCartItems = new byte[4][];
validCartItems[0] = offerKey1;
validCartItems[1] = offerKey1;
validCartItems[2] = offerKey1;
validCartItems[3] = offerKey2;
//Example of ItemPrice in _dataContext.ItemPrices
var itemPriceInFakeContext = new ItemPrice()
{
    OfferKey = offerKey1,
    //some other properties            
};
var itemPrices = _dataContext
    .ItemPrices
    .Where(item => 
         item.UserID == user.UniqueID
         && itemsPartID.Contains(item.PartID)
         && validCartItems.Contains(item.OfferKey)
         && item.CurrencyID == defaultCurrencyCode
         && item.Inventory > 0)
    .ToList();

在这种情况下,找不到任何元素。但如果我们使用数据库,那么一切都可以。

为了解决这个问题,我写了以下代码:

var itemPricesUncheckOfferKey = _dataContext
    .ItemPrices
    .Where(item => 
         item.UserID == user.UniqueID
         && itemsPartID.Contains(item.PartID)
         //&& validCartItems.Contains(item.OfferKey)
         && item.CurrencyID == defaultCurrencyCode
         && item.Inventory > 0)
    .ToList();
List<ItemPrice> itemPrices = new List<ItemPrice>();
foreach (var itemPrice in itemPricesUncheckOfferKey)
{
    foreach (var validCartItem in validCartItems.Distinct())
    {
        if (validCartItem.SequenceEqual(itemPrice.OfferKey))
            itemPrices.Add(itemPrice);
    }
 }

但这看起来并不是一个好的解决方案。你能告诉我LINQ的解决方案吗?

UPD-

UnitTest代码:

[TestMethod]
public void AddCartItems_Test()
{
    User user;
    InitUser(out user);
    List<AddCartItem> addCartItems;
    addCartItems = InitAddCartItem();
    ICartService cartService;
    InitCartService(out cartService);
    List<AddCartItemRezult> addCartItemRezults = cartService.AddCartItems(user, addCartItems);
    Assert.AreEqual(4, addCartItemRezults.Count);
    int countAllGood = 0;
    foreach (var addCartItemRezult in addCartItemRezults)
    {
        if (addCartItemRezult.IsSuccess) countAllGood++;
    }
    Assert.AreEqual(1, countAllGood);
}
 private void InitCartService(out ICartService cartService )
    {
        DataFakeContext dataFakeContext = new DataFakeContext();
        DataContext_InitUsers(ref dataFakeContext);
        DataContext_ItemPrices(ref dataFakeContext);
        DataContext_CartItems(ref dataFakeContext);
        IDeliveryService deliveryService = new DeliveryFakeService(dataFakeContext);
        cartService = new CartService(dataFakeContext, deliveryService);
    }
private void DataContext_ItemPrices(ref DataFakeContext dataFakeContext)
    {
        dataFakeContext.ItemPrices = new ItemPriceDbSet();
        byte[] OfferKeyPriv = { 30, 163, 252, 225, 36, 208, 128, 47, 64, 244, 34, 199, 28, 57, 110, 215 };
        var itemPrice1 = new DataAccess.Sql.NavisionModel.ItemPrice()
        {
            Inventory = 2075,
            ItemID = "475931",
            LineAmount = (decimal)389.9300,
            LineAmountWithMargin = (decimal)522.5062,                                
            Multiplicity = 1,                
            OfferKey = OfferKeyPriv,
            //some other properties
        };
        dataFakeContext.ItemPrices.Add(itemPrice1);
    }

我使用Repository.Pattern.Ef6;

检查数组是否包含在LINQ表达式中的数组数组中

在代码中创建byte[] offerKey1 = ...并将其保存到itemPriceInFakeContext中。您应该使用相同的变量将其添加到_dataContext中。我的意思是完全相同-不是保存值,而是对同一对象的引用

像这样:

//Array of arrays validCartItems values for example
byte[] offerKey1 = { 30, 163, 252, 225, 36, 208, 128, 47, 64, 244, 34, 199, 28, 57, 110, 215 };
byte[] offerKey2 = { 31, 163, 254, 225, 35, 203, 119, 47, 65, 244, 24, 199, 28, 56, 110, 215 };
byte[][] validCartItems = new byte[4][];
validCartItems[0] = offerKey1;
validCartItems[1] = offerKey1;
validCartItems[2] = offerKey1;
validCartItems[3] = offerKey2;
//Example of ItemPrice in _dataContext.ItemPrices
var itemPriceInFakeContext = new ItemPrice()
{
    OfferKey = offerKey1, // use the same object
    //some other properties            
};
// add fake item price to data context
_dataContext.ItemPrices.Add(itemPriceInFakeContext );
var itemPrices = _dataContext
    .ItemPrices
    .Where(item => 
         item.UserID == user.UniqueID
         && itemsPartID.Contains(item.PartID)
         && validCartItems.Contains(item.OfferKey)
         && item.CurrencyID == defaultCurrencyCode
         && item.Inventory > 0)
    .ToList();

这应该会有所帮助。

p.s.您遇到这个问题是因为运行时比较byte[]的方式与执行EFSQL的方式之间存在差异。在运行时,它通过引用进行比较。但是您的LINQ查询(在执行时)将这个byte[]数组(我相信)转换为字符串。在SQL端,它比较将按值进行比较的字符串。

var itemPrices = _dataContext
    .ItemPrices
    .Where(item => 
         item.UserID == user.UniqueID
         && itemsPartID.Contains(item.PartID)
         && validCartItems.Contains(item.OfferKey)
         && item.CurrencyID == defaultCurrencyCode
         && item.Inventory > 0)
    .ToList();

您的LINQ查询中似乎没有错误。请检查dataContext是否已初始化,以及与数据库的连接是否正常。