简体   繁体   中英

How to check Exists records by some fields - Entity Framework

Before I insert a new product, I want to check whether that value already exists in the database. I have some values in some fields that can be null and false.

I created method like this :

public bool IsExists(Guid warrantyId, bool hasColor, Guid? colorId, bool hasSize, Guid? sizeId)
{
    return _products.Any(row => (hasColor && row.ColorId.Value == colorId.Value) && (hasSize && row.SizeId.Value == sizeId.Value) && row.WarrantyId == warrantyId);
}

but it always returns false .

When I remove this part

row.WarrantyId == warrantyId

it works fine. I don't know how can check it .

here is some data in my database:

在此处输入图片说明

I passed this Item to method:

warrantyId:F1F2D639-22AF-618A-7422-4122BB38D545

hascolor:true , ColorId: 47f3d639-18de-5d26-91f7-0cd4465a161a

HasSize:false and SizeId:null

its return false.

I Rewrite Method like this ,and work fine .

 public bool IsExists(Guid warrantyId, bool hasColor, Guid? colorId, bool hasSize, Guid? sizeId)
    {
       var result = _products.Where(row => row.WarrantyId == warrantyId).AsQueryable();
       if (hasColor)
           result = result.Where(row => row.ColorId.Value == colorId.Value).AsQueryable();
       else
           result = result.Where(row=>row.HasColor==false).AsQueryable();
       if (hasSize)
           result = result.Where(row => row.SizeId.Value == sizeId.Value).AsQueryable();
       else
           result = result.Where(row => row.HasSize == false).AsQueryable() ;

        return result.Any();

    }

Like Stephen Muecke pointed in the comment, your database does not have the row with what you are looking for. Also, if I am not mistaken row.SizeId.Value == sizeId.Value will still return true in case row.SizeId.Value in the database is NULL and sizeId.Value is concrete value (not null).

There is a better way to check existence based on multiple columns in case when you know that you will perform a lot of such searches. However, this method requires table alteration. You need to introduce new column EntryHash which is calculated hash of values from other columns. Make it Unique if you need to have only unique set of values. If not, make an index on it anyway. The idea is that your query will be performed over single column only, which will be faster. Here is proposed method to calculate hash (pay attention to nullified values).

public static string CreateEntryHash(Guid warrantyId, bool hasColor, Guid? colorId, bool hasSize, Guid? sizeId)
{
    var sb = new StringBuilder();
    sb.Append(warrantyId);
    sb.Append(hasColor);
    sb.Append(colorId == null ? "null" : colorId.ToString());
    sb.Append(hasSize);
    sb.Append(sizeId == null ? "null" : sizeId.ToString());

    var hash = GetMd5Hash(sb.ToString());

    return hash;
}

public static string GetMd5Hash(string input)
{
    StringBuilder sBuilder = new StringBuilder();
    using (MD5 md5Hash = MD5.Create())
    {
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }
    }

    return sBuilder.ToString();
}

public bool IsExists(Guid warrantyId, bool hasColor, Guid? colorId, bool hasSize, Guid? sizeId)
{
    var hash = CreateEntryHash(warrantyId, hasColor, colorId, hasSize, sizeId);
    return _products.Any(p => p.EntryHash == hash);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM