I have the following method:
var catIds = DetachedCriteria.For<Category>()
.Add<Category>(c => c.TypeCode == "IMA")
.SetProjection(LambdaProjection.Property<Category>(s => s.Id));
This is returning nothing because in the database the field is nchar(10). I want to Trim() the TypeCode value, as follows:
var catIds = DetachedCriteria.For<Category>()
.Add<Category>(c => c.TypeCode.Trim() == "IMA")
.SetProjection(LambdaProjection.Property<Category>(s => s.Id));
but it returns the NHibernate error:
Unrecognised method call in epression c.TypeCode.Trim()
One of the guys here in the office thinks it's because HHibernate doesn't know how to convert .Trim() to SQL (or something along those lines). Can anyone suggest how I can fix this?
Try right-padding the value you're comparing with to the required length, for example:
string cmpValue = "IMA".PadRight(10);
var catIds = DetachedCriteria.For<Category>()
.Add<Category>(c => c.TypeCode == cmpValue)
.SetProjection(LambdaProjection.Property<Category>(s => s.Id));
Your office guys are correct -- the linq provider doesn't know how to translate C# string.Trim() to whatever sql variant it is.
As for the fix, linq can make you do the damndest things -- like padding your data to match CHAR(10) rather than TRIM() to a 'normal' string.
I hope the following code may solve your problem:
Func<string, string> trimmer = (x) => {
return !string.IsNullOrEmpty(x) ? x.Trim() : string.Empty; };
and then use it like:
var catIds = DetachedCriteria.For<Category>()
.Add<Category>(c => trimmer(c.TypeCode) == "IMA")
.SetProjection(LambdaProjection.Property<Category>(s => s.Id));
Related
I'm a newbie both to C# and to LINQ and would appreciate a small push in the right direction.
Firstly, I have an Overrides SQL table (and a corresponding EF DB context), which has a Type, Value, and Override Value. The idea is that for a particular kind ("Type") of override, the code can check a particular value and go see if there is an override value that should be used instead.
var branchOverrides = overridesSqlContext.Overrides
.Where(q => q.Type == "Branch Override")
.Select(s => new
{
s.Value,
s.OverrideValue
});
In this case, I want the list of different override values of the "Branch Override" type. From there, I would like to be able to retrieve a specific override value at a given point within my code. How can I query the branchOverrides variable I've created to be able to say something like:
string readingOverride = select OverrideValue from branchOverrides where Value = "Reading"
My code will need to be able to read various override values for different branches at different points, and being able to query the branchOverrides variable at any point would seem like the ideal approach.
Thank you for any assistance on this.
You can use Single() on the query object you have:
string readingOverride = branchOverrides
.Single(bo => bo.Value == "Reading")
.OverrideValue;
This will throw an exception if an entry doesn't exist though so you probably want to use SingleOrDefault instead and check for a null return.
Also note that the branchOverrides object here is an IQueryable<> which means that every time you use it, it will send a query to the database. You may want to materialise that to a local list by adding .ToList() after the Select(...). Alternatively, you may want to look at caching this data, especially if it's going to be used frequently.
If I understood you right, you want the entry with Value = "Reading" and Type="Branch Override":
var branchOverride = overridesSqlContext.Overrides
.SingleOrdDefault(q => q.Type == "Branch Override"
&& q.Value == "Reading")
.Select(s => new
{
s.Value,
s.OverrideValue
});
if (branchOverride != null)
{
// do whatever ...
}
For performance issue is good to put .ToList() in the end of your LINQ expression if you need to iterante over that list too many times.
var branchOverrides = overridesSqlContext.Overrides
.Where(q => q.Type == "Branch Override")
.Select(s => new
{
s.Value,
s.OverrideValue
}).ToList();
If it you will load the entire list into the memory avoiding to execute the sql query to fetch the data if you need to iterate through your list.
Other thing that you can do is:
string readingOverride = string.Empty;
var branchOverride = branchOverrides.FirstOrDefault(x => x.Value == "Reading");
if(branchOverride != null)
{
readingOverride = branchOverride.OverrideValue;
}
Hope that helps.
If Value is unique within "Branch Override" perhaps you want to turn it to a dictionary for fast lookup
var branchOverrides = overridesSqlContext.Overrides
.Where(q => q.Type == "Branch Override")
.Select(s => new
{
s.Value,
s.OverrideValue
})
.ToDictionary(k => k.Value, v => v.OverrideValue);
Then later on you can find the override value quickly and efficiently
var readingOverride = branchOverrides["Reading"];
I am trying to get the Patient's Firstname from a database but what I am getting when I run this piece of code is just a Linq expression string instead.
public static string GetPatientName(int bedNumber)
{
var name = "";
using (var data = new HospitalDBDataContext())
{
if (data.Connection.State == ConnectionState.Closed)
data.Connection.Open();
name = data.Patients.Where(x => x.BedNumber.Equals(bedNumber))
.Select(x => x.Firstname).ToString();
if (data.Connection.State == ConnectionState.Open)
data.Connection.Close();
data.Dispose();
}
return name;
}
What is the way of making this Expression to return the actual value I need?
name = data.Patients.Where(x => x.BedNumber.Equals(bedNumber))
.Select(x => x.Firstname).ToString();
Should be:
name = data.Patients.Where(x => x.BedNumber.Equals(bedNumber))
.Select(x => x.Firstname).FirstOrDefault();
You need to actually select .First() or .FirstOrDefault(). Right now you are casting the entire IQueryable statement into a string.
The problem is ToString call that gives you the Linq expression
possible solutions. using FirstOrDefault to get first name.
name = data.Patients.Where(x => x.BedNumber.Equals(bedNumber)).Select(x => x.Firstname).FirstOrDefault();
Or use string.Join to get all the names in one string with separator like ,(the first parameter passed to string.join).
name = string.Join(", " ,data.Patients.Where(x => x.BedNumber.Equals(bedNumber)).Select(x => x.Firstname));
The Where method returns an Enumerable<T> of results (patients), and the Select method returns a new Enumerable<string> with the Firstnames of each patient.
Instead of converting that Enumerable<string> to a string, you need to use a method like Single or First to get one object out of it.
(Single will throw an exception if there is more than one object in the Enumerable<T>, and First will throw an exception if there are no objects in the Enumerable<T>. Use SingleOrDefault or FirstOrDefault if you want null instead of an exception in those cases.)
I want do something like this:
string test = alarmType;
db.Alarms.Where(alarmType.Contains(m => m.Type)).ToList();
But this doesn't work. How can I make such query? Is it the only way to use pure SQL?
UPD
I'm trying to find whether records is substring of the "test", not conversly.
You have to reverse the condition:
var query = db.Alarms
.Where(a => alarmType.Contains(a.Type))
.ToList();
However, your code sample is confusing, if alarmType is a string i don't know what you're trying to achieve.
string test = alarmType;
Update: if you're using LINQ-To-Sql and you want to find all records where the Type is a substring of alarmType you can use:
var query = db.Alarms
.Where(a => SqlMethods.Like(alarmType, string.Format("%{0}%", a.Type)))
.ToList();
Try the following
string test = alarmType;
var result = db.Alarms.Where(m => alarmType.Contains(m.Type)).ToList();
Your LINQ query isn't well-formatted. You have:
db.Alarms.Where(alarmType.Contains(m => m.Type)).ToList();
So the parameter you've passed to Contains is a lambda, which isn't what Contains takes,
Likeiwse, Contains returns a bool, so you've passed a bool to Where, which is also not a parameter type it takes.
What you want is to pass a lambda to Where, like so:
db.Alarms.Where(m => alarmType.Contains(m.Type)).ToList();
Note how now both the Where and the Contains are being passed parameters of the correct type.
Following code block throws error.
LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.
db.tbOnIgmHawbDetails
.Where(s => !db.tbImpoExaminations.Any(x => x.Hawb.ToString() == s.Hawb) && s.AwbNo == p)
.Select(s => s.Hawb).ToList();
Any suggestion? why this happen and what is the solution?
.ToString() is supported properly going forward with EF 6.1: http://blogs.msdn.com/b/adonet/archive/2014/03/17/ef6-1-0-rtm-available.aspx
You could try with SqlFunctions.StringConvert... Use the decimal conversion:
SqlFunctions.StringConvert((decimal)p.x.Hawb).TrimLeft() == ...
(the TrimLeft is necessary because the STR function of SQL will right align the number)
If s.Hawb is already string type (the error message suggests so), then remove the part .ToString() from your query.
The reason for it is that in LINQ2SQL, you can only use those language constructs that can be translated into SQL. For example, if you try to use RegEx in your C# expression, then SQL does not have a corresponding construct for RegEx, and thus LINQ cannot translate and execute your query.
Easily add .AsEnumerable() before the .ToString() and those methods that L2E doesn't support:
var asen = db.tbOnIgmHawbDetails.AsEnumerable();
var result = asen.Where(s => !asen.Any(x => x.Hawb.ToString() == s.Hawb) && s.AwbNo == p)
.Select(s => s.Hawb).ToList();
That should works. However if not, try to perform your query by linq-to-objects syntax:
var result = from a in asen
where ...
select ...;
do not use ToString
just use like
x.Hawb + "" == s.Hawb
I have a LINQ query which returns all the values inside a Dictionary, conditional upon something:
var apps =
from entry in shape.Decorators
where entry.Value == DecoratorLayoutStyle.App
select entry.Key;
shape.Decorators is a
Dictionary<Shape, DecoratorLayoutStyle>
Is there something terser, and/or can I use a combination of lambdas or something?
var apps = shape.Decorators
.Where(x=>x.Value == DecoratorLayoutStyle.App)
.Select(x=>x.Key);
I think yours is just as fine.
That looks plenty terse to me, I guess you could use the extension functions instead of the from/select linq syntax, but that wouldn't be too different.
More imporantly, I'm not sure you want terser. The current format is very readable, and clearly documents exactly what you're trying to do.
var apps = shape.Decorators
.Where(e => e.Value == DecoratorLayoutStyle.App)
.Select(e => e.Key);
Do you think this is terser?
Personally I prefer the query syntax when I have more than one LINQ operator all the operators I use can be translated to it.
var apps = Shape.Decorators.Where(x => x.Value == DecoratorLayoutStyle.App)
.Select(x => x.Key);
Just to be different.
var apps = shape.Decorators.Keys
.Where(k => shape.Decorators[k] == DecoratorLayoutStyle.App);