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

时间:2016-05-03 15:14:25

标签: c# arrays linq

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

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

2 个答案:

答案 0 :(得分:0)

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是否已初始化以及与数据库的连接是否正常。

答案 1 :(得分:0)

在您的代码中,您创建了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端,它比较将按值进行比较的字符串。