Reputation: 852
I have a linq query where sometimes the string field, product name, may be empty, null. This is a new field in the table and if data hasn't been entered, then I get an error when running the query. What I need to do is check for null and if null replace the null/empty value with the text value from a drop down list. I've tried several things but can't get it to work.
public IQueryable<Product> BindProduct([Control("ddProductName")] int? ProductNameId)
{
var prod = from c in _DbContext.Products
where c.ProductNameId == ProductNameId
orderby string.IsNullOrEmpty(c.ProductName) ? ddProductName.SelectedItem.Text : c.ProductName,
c.ItemNumber
select c;
return prod;
}
CHANGED TO:
public IQueryable<Product> BindProduct([Control("ddProductName")] int? ProductNameId)
{
var prodName = ddProductName.SelectedItem.Text;
var prod = from c in _DbContext.Products
where c.ProductNameId == ProductNameId
let sortName = c.Name ?? prodName
orderby sortName, c.ItemNumber
select new { c, sortName };
return prod;
}
UPDATE: I don't think I was clear. What I need to do is check for null and if null replace the null/empty value with the text value from a drop down list.
Upvotes: 4
Views: 11060
Reputation: 852
The answer came from a peer of mine, Brad. For anyone else who is wondering how to replace a null/empty value using linq, see below.
public IQueryable<Product> BindProduct([Control("ddProductName")] int? ProductNameId)
{
var prodName = ddProductName.SelectedItem.Text;
var prod = _DbContext.Products.Where(c => c.ProductNameId == ProductNameId).ToList().Select
(p =>
{
p.Name = string.IsNullOrEmpty(p.Name) ? prodName : p.Name;
return p;
}).OrderBy(p => p.Name).ThenBy(p => p.ItemNumber).AsQueryable();
return prod;
}
Upvotes: 2
Reputation: 2315
"Let" keyword should do the trick.
Here is a LINQPad example:
var products = Enumerable.Range(0, 100).Select(q => new {ProductNameId = 1, ProductName = (q % 15 == 0 ? null : (q % 3 == 0 ? "Fizz" : (q % 5 == 0 ? "Buzz": q.ToString()))), ItemNumber = q});
var ddProductName_SelectedItem_Text = "FizzBuzz";
var ProductNameId = 1;
var prod = from c in products
where c.ProductNameId == ProductNameId
let sortName = c.ProductName ?? ddProductName_SelectedItem_Text
orderby sortName, c.ItemNumber
select c;
return prod; //prod.Dump(); //for linqpad debugging
Upvotes: 7
Reputation: 145
When you call the orderby in your query, LINQ to SQL will attempt to resolve it into an order by statement in SQL. Since SQL has no method for a conditional order by statement, the method will fail to compile from LINQ.
What you want can be achieved, but it will require ordering the set client side instead of server side. My suggestion would be to run the query without the order by, and at the point that you need to order, first transform the collection to an IEnumerable collection. This will pull into memory the results from the IQueryable, and you'll be able to run the orderby against the object collection.
The basic flow will be something like this: queryable.AsEnumerable().OrderBy()
The big takeaway here is to remember that LINQ will try to transform an IQueryable into a SQL query at the point at which you request an enumeration over the collection. There is a pretty good high level explanation here: http://blog.worldmaker.net/2013/mar/11/mini-lecture-linq-visualization/.
Upvotes: 1