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.)
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"];
Let's say I have a class in EF named vw_Project with a property ProjectTitle of type string, among other properties. I want to run an efficient LINQ query which only queries the first column of the first record in my results (the first "cell", similar to SqlCommand.ExecuteScalar). I might write something like this:
string projectTitle = context.vw_Projects
.Where(p => p.ProjectID == projID)
.Select(p => p.ProjectTitle)
.FirstOrDefault();
The problem is, I can't tell whether my query got zero results, or if it simply got one result with a value of NULL for that varchar column.
I could always query the whole object to make that determination, then extract the ProjectTitle column into a string variable in memory, but I'd be querying a bunch of columns I don't need, which is a poor solution. That would look like this:
string projectTitle;
vw_Project project = context.vw_Projects
.Where(p => p.ProjectID == projID)
.FirstOrDefault();
if (project != null)
{
projectTitle = project.ProjectTitle;
}
else
{
throw new Exception("Invalid Project ID");
}
How do I make this determination without querying additional columns or rows?
You can still determine whether you got zero results or a NULL record if you create an in-line anonymous type with only the property you need.
string projectTitle;
var result = context.vw_Projects
.Where(p => p.ProjectID == projID)
.Select(p => new { p.ProjectTitle })
.FirstOrDefault();
if (result != null)
{
projectTitle = result.ProjectTitle;
}
else
{
throw new Exception("Invalid Project ID");
}
If the query gets a result, the result instance will not be null, regardless of whether the internal ProjectTitle property is null.
I am using MVC 4 and entity framework, I am retrieving emails from the server:
var data = db.Candidates.Where(c => ids.Contains(c.ID) && c.Email1 != null).Select(c => new { c.Email1, c.ID }).ToList();
My first question: Does LINQ allow me to return an empty string form the Email1 field if it is null, similar to SQL coalesce? (I would remove the null test from the where clause).
2nd question: what would be the easiest object to use (to replace the "var data =" if I wanted to get c.Name along with the Email1, then use both in a loop? Should I create a model for just 2 fields?
Thanks so much in advance for any insights.
My first question: Does LINQ allow me to return an empty string form the Email1 field if it is null, similar to SQL coalesce? (I would remove the null test from the where clause).
Yes, there is the ?? operator that works similar to the coalesce.:
new { Email1 = c.Email1 ?? "", c.ID } //String.Empty would be nicer, but i think it depends on EF version if you are allowed to use it.
For your second question, if this is the only place you are going to use them, then anonymous is pretty fine.
If you want to use this on other places, yes create an object just with two properties... That's the object's purpose after all. (or maybe a struct?)
Ask one question at a time.
2a. The Null Coalescence operator in C# is ??.
2b. This may or may not be converted by your Linq Provider into a database query.
Do it like this,
var data = db.Candidates
.Where(c => ids.Contains(c.ID))
.Select(c => new
{
Id = c.Id,
Email1 = c.Email1 ?? string.Empty,
Name = c.Name
});
foreach(var row in data)
{
var name = row.Name // etc...
}
If your Linq Provider does not support the ?? operator, put in a .ToList() and use linq-to-objects to perform the tranformation like this,
var data = db.Candidates
.Where(c => ids.Contains(c.ID))
.ToList() // <-- from here is Linq-To-Objects
.Select(c => new
{
Id = c.Id,
Email1 = c.Email1 ?? string.Empty,
Name = c.Name
});
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.
Consider the following examples, in all of which, I am trying to get the code and the name of a province/state having a known ID, into a single string variable, with a format like "CA-California":
string stateName = _repository.States.Single(s => s.StateId == stateId).Name;
string stateCode = _repository.States.Single(s => s.StateId == stateId).Code;
string stateCodeName = stateCode + "-" + stateName;
var state = _repository.States.Single(s => s.StateId == stateId);
string stateCodeName = state.Code + "-" + state.Name;
string stateCodeName = _repository.States.Where(s => s.StateId == stateId)
.Select(s => s.Code + "-" + s.Name)
.First();
In the first example, only the needed properties of the state are retrieved, but at the cost of running two different queries. The second example runs one query only, but it retrieves all of the properties of the state. The third example seems to be all right, but my question is if there is a way to use Single and First methods to retrieve an arbitrary number of properties from an object (or columns from a table), as opposed to getting them all or only one at a time?
Thank You
my question is if there is a way to use Single and First methods to
retrieve an arbitrary number of properties from an object (or columns
from a table), as opposed to getting them all or only one at a time?
You can use an anonymous type to do this:
var state = _repository.States.Where(s => s.StateId == stateId)
.Select(s => new { Code = s.Code, Name = s.Name })
.First();
This will return an anonymous type with two properties: Code and Name.
(Whether you use First() or Single() depends on how you want the program to behave if there is more than one match. Single() would throw an exception if there was more than one.)
If you were to change the use of First() to Single() in your third example, you would have exactly the query you're looking for.
The query would return only the single result that you're expecting and would only return the fields (already concatenated) that you're interested in.