I have a db request that could return null:
Pony MyPony = db.Pony.Where(p => p.PonyOwnerId == user.UserId).First();
If there is no row in my db, there is an error message.
How to accept an empty query?
You can use FirstOrDefault
Pony myPony = db.Pony.Where(p => p.PonyOwnerId == user.UserId).FirstOrDefault();
if (myPony == null)
{
..
}
You can write:
Pony myPony = db.Pony.Where(p => p.PonyOwnerId == user.UserId).FirstOrDefault();
if( myPony != null ) {
// Do something
}
var MyPony = db.Pony.FirstOrDefault(p => p.PonyOwnerId != null && p.PonyOwnerId == user.UserId);
or
var MyPony = db.Pony.Where(p => p.PonyOwnerId != null && p.PonyOwnerId == user.UserId).FirstOrDefault();
or
if (db.Pony.FirstOrDefault(p => p.PonyOwnerId != null && p.PonyOwnerId == user.UserId) != null)
{
//Do stuff
}
Related
I have looked at similar questions but none have really been able to answer my question.
All I want to do is make a select using lambda but the trick is, there is a variable amount of OR/AND conditions for the selection. My function receives a list of AND conditions and it should select based on that.
Here is what I have right now and it supports up to 10 AND conditions passed as a string to compare, but this code is terrible.. in reality it should be able to accept an undefined/variable amount of conditions.
Not sure how to go about this..
ProductTags is a list of tags.. if the product has all of the tags then it is returned.
public static List<product> FilterProductsByTagsAll(List<string> tags)
{
List<product> products = new List<product>();
switch (tags.Count)
{
case 1:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()).ToList();
break;
case 2:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()).ToList();
break;
case 3:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()).ToList();
break;
case 4:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()).ToList();
break;
case 5:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()).ToList();
break;
case 6:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()).ToList();
break;
case 7:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()).ToList();
break;
case 8:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[7]).Any()).ToList();
break;
case 9:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[7]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[8]).Any()).ToList();
break;
case 10:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[7]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[8]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[9]).Any()).ToList();
break;
default:
break;
}
return products;
}
Thank you for trying to help out.
Try this query:
var allTagsProds = Database.Products.Values.Where(p => p.ProductTags != null && p.ProductTags.Select(pt => pt.Tag_name).Intersect(tags).Count() == tags.Count());
For each product, it selects the product tag names then intersects them with the tags list. This produces a list of product tag names that match the tags list.
Then it compares the count of this list with the count of the tags list and if they are the same, the product has all the tags. These are then returned.
Example using hard coded models:
public class Tag {
public string Tag_name {get; set;}
}
public class Product {
public ICollection<Tag> ProductTags {get; set;}
public string Name {get; set;}
}
public class Program
{
public static void Main()
{
List<string> tags = new List<string> {"a","b","c","d","e","f"};
var prodTags = new List<Tag>() {
new Tag() {Tag_name = "a"},
new Tag() {Tag_name = "b"},
new Tag() {Tag_name = "c"},
new Tag() {Tag_name = "d"}
};
var prodTags2 = new List<Tag>() {
new Tag() {Tag_name = "a"},
new Tag() {Tag_name = "b"},
new Tag() {Tag_name = "c"},
new Tag() {Tag_name = "d"},
new Tag() {Tag_name = "e"},
new Tag() {Tag_name = "f"}
};
var products = new List<Product>() {
new Product() { Name="Prod1", ProductTags = prodTags },
new Product() { Name="Prod2",ProductTags = prodTags2 }
};
var allTagsProds = products.Where(p => p.ProductTags != null && p.ProductTags.Select(pt => pt.Tag_name).Intersect(tags).Count() == tags.Count());
foreach(var prod in allTagsProds)
{
//Writes "Prod2"
Console.WriteLine(prod.Name);
}
}
}
This code was working before but now I've got this error: The cast to value type 'System.Boolean' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
public async Task<ActionResult> BankDepositVoucher(BankDepositVoucherSearchViewModel search, int? PageNo)
{
var model = new BankDepositVoucherListViewModel
{
Search = search ?? new BankDepositVoucherSearchViewModel()
};
if (search != null)
{
search.StartDate = search.StartDate.ToStartOfDay();
search.EndDate = search.EndDate.ToEndOfDay();
}
try
{
var Vouchers = DbManager.Invoices.Include(x => x.BankDepositVoucher)
.Where(x => x.Type == InvoiceType.BankDepositVoucher
&& (x.VoucherNumber == search.VoucherNo || search.VoucherNo == null)
&& (x.BankDepositVoucher.SlipNo.Contains(search.SlipNo) || search.SlipNo == null)
&& (x.BankDepositVoucher.ChequeNo.Contains(search.ChequeNo) || search.ChequeNo == null)
&& (x.BankDepositVoucher.Bank.AccountName.Contains(search.BankDetails)
|| search.BankDetails == null)
&& (x.BankDepositVoucher.AccountName.Contains(search.AccountName) || search.AccountName == null)
&& (x.BankDepositVoucher.Narration.Contains(search.Narration) || search.Narration == null)
&& (x.TotalAmount == search.Amount || search.Amount == null)
&& (x.Date >= search.StartDate || search.StartDate == null)
&& (x.Date <= search.EndDate || search.EndDate == null));
//model.Pager = new Pager(await Vouchers.CountAsync(), PageNo, 10);
model.Vouchers = await Vouchers.OrderByDescending(x => x.VoucherNumber)
//.Skip((model.Pager.CurrentPage - 1) * model.Pager.PageSize)
//.Take(model.Pager.PageSize)
.Select(x => new BankDepositVoucherBaseViewModel
{
Id = x.Id,
VoucherNumber = x.VoucherNumber,
AccountName = x.BankDepositVoucher.AccountName,
BankAccountName = x.BankDepositVoucher.Bank.AccountName,
Date = x.Date,
ChequeNo = x.BankDepositVoucher.ChequeNo,
Narration = x.BankDepositVoucher.Narration,
SlipNo = x.BankDepositVoucher.SlipNo,
TotalAmount = x.TotalAmount,
IsCleared = x.BankDepositVoucher.IsCleared
}).ToListAsync();
}
catch (Exception ex)
{
Console.WriteLine("", ex.Message);
}
return PartialView(model);
}
This is the part throwing above mentioned exception
model.Vouchers = await Vouchers.OrderByDescending(x => x.VoucherNumber)
//.Skip((model.Pager.CurrentPage - 1) * model.Pager.PageSize)
//.Take(model.Pager.PageSize)
.Select(x => new BankDepositVoucherBaseViewModel
{
Id = x.Id,
VoucherNumber = x.VoucherNumber,
AccountName = x.BankDepositVoucher.AccountName,
BankAccountName = x.BankDepositVoucher.Bank.AccountName,
Date = x.Date,
ChequeNo = x.BankDepositVoucher.ChequeNo,
Narration = x.BankDepositVoucher.Narration,
SlipNo = x.BankDepositVoucher.SlipNo,
TotalAmount = x.TotalAmount,
IsCleared = x.BankDepositVoucher.IsCleared
}).ToListAsync();
The issue is likely that when populating the view model it cannot deal with the fact that a record may not have a BankDepositVoucher.
For instance:
IsCleared = x.BankDepositVoucher.IsCleared
This should probably be:
IsCleared = x.BankDepositVoucher?.IsCleared ?? false
One other thing to improve performance considerably:
While it may look concise in the code to write statements like this:
.Where(x => x.Type == InvoiceType.BankDepositVoucher
&& (x.VoucherNumber == search.VoucherNo || search.VoucherNo == null)
&& (x.BankDepositVoucher.SlipNo.Contains(search.SlipNo) || search.SlipNo == null)
&& (x.BankDepositVoucher.ChequeNo.Contains(search.ChequeNo) || search.ChequeNo == null)
&& (x.BankDepositVoucher.Bank.AccountName.Contains(search.BankDetails)
|| search.BankDetails == null)
&& (x.BankDepositVoucher.AccountName.Contains(search.AccountName) || search.AccountName == null)
&& (x.BankDepositVoucher.Narration.Contains(search.Narration) || search.Narration == null)
&& (x.TotalAmount == search.Amount || search.Amount == null)
&& (x.Date >= search.StartDate || search.StartDate == null)
&& (x.Date <= search.EndDate || search.EndDate == null));
It is more efficient to write it out as:
.Where(x => x.Type == InvoiceType.BankDepositVoucher);
if(!string.IsNullOrEmpty(search.VoucherNo))
Voucher = Voucher.Where(x => x.VoucherNumber == search.VoucherNo);
if(!string.IsNullOrEmpty(search.SlipNo))
Voucher = Voucher.Where(x => x.BankDepositVoucher.SlipNo.Contains(search.SlipNo))
// etc.
The reason is that in the first case you are generating a much larger SQL statement to be sent to the database, and it is quite easy to "slip up" on conditions if that query is ever edited in the future. (missing parenthesis, etc.) The second example only adds conditions to the query if they are needed, keeping the resulting SQL statement much more compact.
Am using ASP.NET MVC 5 to create an Application for billing, now i have thing function which receive a filter object with different variables, am having a problem with contains when i search, what am i doing wrong
public static List<Quote> getCustomerQuotes(QuoteFilter filter)
{
using (var db = new AppDBContext())
{
var q = db.Quotes.Where(u => u.entryDate > 0); ;
if (filter.type != null)
{
q = q.Where(u => u.quoteType == filter.type);
}
if (filter.only_permitable != null)
{
q = q.Where(u => !Values.NON_PERMITABLE_QUOTES.Contains(u.quoteType));
}
if (filter.quote_status != null)
q = q.Where(u => u.quote_status == (int)filter.quote_status);
if (filter.quotenumber != null)
{
q = q.Where(u => u.quote_number.Contains(filter.quotenumber));
}
if (filter.permitnumber != null)
q = q.Where(u => u.permit_number.Contains(filter.permitnumber));
if (filter.permit_status != null)
q = q.Where(u => u.permit_status == (int)filter.permit_status);
if (filter.quoteId != null)
q = q.Where(u => u.Id == (int)filter.quoteId);
if (filter.customer_id != null)
q = q.Where(u => u.customer_id == (int)filter.customer_id);
q = q.OrderByDescending(u => u.Id);
FileLogger.Log("getCustomerQuotes", q.ToString());
return q.ToList();
}
}
When i call the function and pass quotenumber, the contains doesnt search, it returns nothing
You have to evaluate your expression, before you apply the OrderByDescending.
q = q.Where(u => u.quote_number.Contains(filter.quotenumber)).ToList();
This should be happen also to the rest places.
Is quote number alpha-numeric? If yes, as Contains is case sensitive can you try comparison by first turning source and target to same case ? like
q = q.Where(u => u.quote_number.ToLower().Contains(filter.quotenumber.ToLower()));
Cheers
Ok, am answering my own question after finding a solution or i may call it a hack
public static List<Quote> getCustomerQuotes(QuoteFilter filter)
{
using (var db = new AppDBContext())
{
var q = db.Quotes.Where(u =>
(filter.type != null ? u.quoteType == filter.type : u.quoteType > 0) &&
(filter.only_permitable != null ? !Values.NON_PERMITABLE_QUOTES.Contains(u.quoteType) : u.permitType > 0) &&
(filter.quote_status != null ? u.quote_status == filter.quote_status : u.quote_status > -100) &&
(!string.IsNullOrEmpty(filter.quotenumber) ? u.quote_number.Contains(filter.quotenumber) || u.groupName.Contains(filter.quotenumber) : u.quoteType > 0) &&
(!string.IsNullOrEmpty(filter.permitnumber) ? u.permit_number.Contains(filter.permitnumber) || u.groupName.Contains(filter.permitnumber) : u.quoteType > 0) &&
(filter.permit_status != null ? u.permit_status == filter.permit_status : u.quoteType > 0) &&
(filter.quoteId != null ? u.Id == filter.quoteId : u.Id > 0) &&
(filter.customer_id != null ? u.customer_id == filter.customer_id : u.customer_id > -1)
).OrderByDescending(u => u.Id);
//FileLogger.Log("getCustomerQuotes", q.ToString());
return q.ToList();
}
}
i dont know why it didn't work the first time but now it works.
I ask myself how I can simplify something like this
var myList = new List<MyObject>
pulic MyObject FindBestMatching(int Prop1Value, int Prop2Value, int Prop3Value)
{
MyObject item = null;
item = myList.Find(x => x.Prop1 == Prop1Value && x.Prop2 == Prop2Value && x.Prop3 == Prop3Value);
if(item != null)
{
return item;
}
item = myList.Find(x => x.Prop1 == Prop1Value && x.Prop2 == Prop2Value);
if(item != null)
{
return item;
}
item = myList.Find(x => x.Prop1 == Prop1Value);
// Doesn't matter if its null
return item;
}
I'm sure LINQ offers a solution, but I'm not able to find it :)
Thank you.
Technically, you can simplify the current code into
pulic MyObject FindBestMatching(int Prop1Value, int Prop2Value, int Prop3Value) {
return
myList.Find(x => x.Prop1 == Prop1Value && x.Prop2 == Prop2Value && x.Prop3 == Prop3Value)
?? myList.Find(x => x.Prop1 == Prop1Value && x.Prop2 == Prop2Value)
?? myList.Find(x => x.Prop1 == Prop1Value);
}
But doing Find (scaning the entire list) can be a costly operation, if it's your case you can find the best match in one loop only:
public MyObject FindBestMatching(int Prop1Value, int Prop2Value, int Prop3Value) {
MyObject result1 = null;
MyObject result2 = null;
foreach (MyObject item in myList) {
if (item.Prop1 == Prop1Value) {
result1 = item;
if (item.Prop2 == Prop2Value) {
result2 = item;
if (item.Prop3 == Prop3Value)
return item;
}
}
}
return result2 ?? result1;
}
Try this:
public MyObject FindBestMatching(int Prop1Value, int Prop2Value, int Prop3Value)
{
return myList.FirstOrDefault(x => (x.Prop1 == Prop1Value && x.Prop2 == Prop2Value && x.Prop3 == Prop3Value)
|| (x.Prop1 == Prop1Value && x.Prop2 == Prop2Value)
|| (x => x.Prop1 == Prop1Value));
}
I'm trying to code a method that, in it's class given the values of some of the attributes, returns a filtered DbSet. The code, so far, is:
public IEnumerable<Pesquisa> Pesquisas {
get {
PrometheusDBContext db = new PrometheusDBContext();
var temp = db.Pesquisas;
if ((this.Filtro.Nome != null) && (this.Filtro.Nome.Trim() != ""))
{
temp = (temp.Where(p => SqlFunctions.PatIndex(this.Filtro.Nome, p.Nome) > 0) as DbSet<Pesquisa>);
}
if ((this.Filtro.CodTipoPesquisa != null) && (this.Filtro.CodTipoPesquisa.Trim() != ""))
{
temp = (temp.Where(p => p.CodTipoPesquisa == this.Filtro.CodTipoPesquisa.Trim()) as DbSet<Pesquisa>);
}
if ((this.Filtro.IDStatusPesquisa != null) && (this.Filtro.IDStatusPesquisa > 0))
{
temp = (temp.Where(p => p.IDStatusPesquisa == this.Filtro.IDStatusPesquisa) as DbSet<Pesquisa>);
}
if ((this.Filtro.DataCriacao_Inicial != null) && (this.Filtro.DataCriacao_Final != null))
{
temp = (temp.Where(p => (p.DataCriacao >= this.Filtro.DataCriacao_Inicial) && (p.DataCriacao <= this.Filtro.DataCriacao_Final)) as DbSet<Pesquisa>);
}
else
{
if (this.Filtro.DataCriacao_Inicial != null)
{
temp = (temp.Where(p => p.DataCriacao >= this.Filtro.DataCriacao_Inicial) as DbSet<Pesquisa>);
}
if (this.Filtro.DataCriacao_Final != null)
{
temp = (temp.Where(p => p.DataCriacao <= this.Filtro.DataCriacao_Final) as DbSet<Pesquisa>);
}
}
return temp
.Include(p => p.Usuario)
.Include(p => p.StatusPesquisa)
.Include(p => p.TipoPesquisa)
.Include(p => p.ModeloTermoAdesao)
.Include(p => p.Pacientes)
.ToList();
}
Problem is: everytime one of the attributes is filled with some value (i.e.: this.Filtro.Nome = "test" ), the ToList() raises an ArgumentNullExcpetion. Any ideas?
You shouldn't cast to DbSet at the end of each line.
Also, declare
IQueryable<Pesquisa> temp = db.Pesuisas;
// your code follows.
The reason behind it is that although you start with a DbSet, applying operators changes its type. Your dynamic cast returns null then.