Get a specific column value from a table when query through linq - c#

var Sent = request.Transactions.First(x => x.isSent == "4");
When the above query runs it gets the complete list of a table row
when condition meets. I just want a specific column value
Date_Sent.
Can I also create a if statement to check if the Date_Sent is null
or not?

TheFirst returns an item of the collection's type. Simple access it's property.
var sent = request.Transactions.FirstOrDefault(x => x.isSent=="4")?.Data_Sent;
If(sent == null) { }
See 2 things:
I suggest you use FirstOrDefault instead. It will not throw an exception if no item in sequence match predicate.
Use the ?. to access the property. It is called Null Propagation
If you do want to use the .Select then thr nicer way without creating temporary anonymous objects or breaking it into separate commands is to use the query syntax instead like this:
var sent = (from item in request.Transactions
where item.isSent =="4"
select Sent_Data).FirstOrDefault()
By the way I'd recommend looking into naming conventions in C#

Related

How to apply filter in child tables using Linq

Net application. I have one entity with child entities. I have to filter based on child entity values. For example in the below query,
var sourceProposal = proposals.ProposalResults.Where(x => x.Quotes.All(c => c.QuotationId.ToLower().Trim() == sourceQuoteId.ToLower().Trim()));
I have input parameter sourceQuoteId which is present in child table quotes. Here parent table is Proposal. So there will be multiple proposal and each proposal has multiple quotes. Idea is to filter proposal based on the quote id. Above query works fine whenever only one quote exists but it will not filter when there are multiple quotes. Can someone help me to filter based on child table?
It seems that you should be calling Any rather than All, if what you want is proposals with any quote that satisfies the criterion.
The reason you are getting this working only when 1 result is in the collection is because you are using an All operator, All operator is used to check whether all elements in a sequence satisfy given condition or not.
What you want to use is the Any operator, Any operator is used to check whether any single element in a sequence satisfy a given condition or not.
Your query should then be:
var sourceProposal = proposals.ProposalResults
.Where(x => x.Quotes.Any(c => c.QuotationId.ToLower().Trim() == sourceQuoteId.ToLower().Trim()));
try this:
var sourceProposal = proposals.ProposalResults.Where(x => x.Quotes.Any(c => c.QuotationId.ToLower().Trim() == sourceQuoteId.ToLower().Trim()));

select unique list from list<string> using linq and substring c#

I have
List<string> fileListServiceLine;
below are the values in the list;
A073662937EMC900200202EST PT-OFF/OPD VISIT 0016224DIAGNOSTIC LAB TEST
A098281448EMC900700103EST PT-OFF/OPD VISIT 0016111SELFCARE TRAINING
I have an identifier
string identifier = EMC9002002;
I get this identifier value from config file.
In my practical case scenario I get more than 2 values in the list string mentioned above.
I am trying to filter the list fileListServiceLine and get only those values which match identifier.
identifier will be present in one of the items in the fileListServiceLine list and only one list item will be a matching case.
I am trying the below code it is not giving the exact result.
var servLineRecords = fileListServiceLine.GroupBy(s => s.Substring(location.ServiceLineIdentifierStart - 1, location.ServiceLineIdentifierLength) == identifier );
location.ServiceLineIdentifierStart and location.ServiceLineIdentifierLength
I will get above values from config file to locate the exact position of identifer matching value.
Thanks In Advance.
Use this linq statement:
var servLineRecords = fileListServiceLine.Where(s => s.ToLower().Contains(identifier.ToLower())).FirstOrDefault();
I would recommend using Contains() combined with some lower-casing using ToLower() on both of the strings to find the matching element. FirstOrDefault() returns default value if no element is found.
var record = fileListServiceLine.Where(s => s.ToLower().Contains(identifier.ToLower())).FirstOrDefault();
You need to use the Contains() method instead like below. Since you know there will be only one value matching the identifier you can use First() and get the first item
fileListServiceLine.Where(s => s.Contains(identifier)).First();
In case, you want to do a case insensitive search then use IndexOf() method instead like
fileListServiceLine.SingleOrDefault(s => s.IndexOf(identifier, StringComparison.OrdinalIgnoreCase) >= 0);
You can use either Single or SingleOrDefault. e.g,
fileListServiceLine.Single(s => s.Contains(identifier));
Single will throw an exception if there isn't exactly one match, whereas SingleOrDefault will instead return null.

Linq Query returning null parameters when selecting whole table

I'm quite new to Linq but have been using it a lot recently and have been growing in confidence. I am accessing my db via a Context within an MVC project using EF.
All I want to do in this instance is fetch all data from one of my tables.
var msgs = context.Messages.ToList();
I feel like this is fine, however when I later use the list:
foreach(Message m in msgs)
{
var info = context.Contacts.Where(x => x.Id == m.recipient.Id)
.Select(x => x.MobileNumber).FirstOrDefault();
}
The Message object has a mandatory Recipient which is a Contact object (another entity in my database).
I get a NullArgumentException on the line above because the Recipient parameter of the message objects are null in my list, despite them not being null in the database.
The strange thing is that the list is the right size, so it enters the foreach loop. The list is being correctly selected but all of the properties are null according to my debugger.
Confused by this I ran the line:
console.WriteLine(context.Messages.Select(x => x.Recipient.FirstName).FirstOrDefault());
and the first name of the Recipient of the first message was written to the console fine. So when I select individually I can retrieve the Recipient of the message and all of their information, but when trying to retrieve the entire table and store it in a list the recipient object is null.
Like I said, I am accessing this from outside of my MVC project which contains the context. I am utilising it from another project. This other project however contains references to both my MVC project which contains the db's Message model, and another project which contains a different class called Message. Could this ambiguity be the source of the problem or is there something else wrong with what I am doing?
EDIT I've created a bit of confusion about my issue apparently. The problem is that once I retrieve the list, the list is of the correct size, but the parameters of the message objects in the list are null. So for example if I write:
foreach (Message m in msgs)
{
Console.WriteLine("List Element Exists");
if (m.Recipient != null)
{
Console.WriteLine(m.Recipient.FirstName);
}
}
I get the output:
List Element Exists
List Element Exists
List Element Exists
List Element Exists
for each element in the list.
JK
most probably the result of where condition is null in the linq query.
var info = context.Contacts.Where(x => x.Id == m.recipient.Id)
.Select(x => x.MobileNumber).FirstOrDefault()
Also the query itself has some problems, you may write the same query as:
var mobileNumber = string.Empty; //if it is not a string then initialize with proper value
var info = context.Contacts.FirstOrDefault(x => x.Id == m.recipient.Id);
if(info != null)
mobileNumber = info.MobileNumber;
Also there is another problem; if you execute this line:
var msgs = context.Messages.ToList();
it will fetch all Messages from DB; but you only need one phone number. So instead of fetching all records just execute the query I have provided and do not call foreach.
Edit
When ToList() is executed, db query is executed immediately; which means that Recipient property of Message object will not be loaded. Depending on whether you are using Lazy Loading or Eager Loading, you need another mechanism to fetch the Recipient property. Something like;
var msgs = context.Messages.Include(b => b.Recipients).ToList();
If you expect that msg.Recipient contains something (i.e. on DB the data is compiled), it's a mapping issue. The most common issue is that Recipient property is not marked as virtual.
EDIT
Or, even worst, the class is marked as sealed but this usually does not happen

Check for items inside a Entity Framework linq result

I am trying to check to see if any results were returned from an entity framework query before acting upon it, I'm trying to use the code :-
var shoppingCartSessions = from c in context.ShoppingCartSessions where c.UserId == gUserID select c;
if (shoppingCartSessions.First() != null)
{
}
However I get the error
Sequence contains no elements
I have checked around stack and found that I can replace .First with .FirstOrDefault however I wanted to check if this is the correct way to be checking for existence of elements. Is there a better way rather than trying to fetch the item and then checking it?
Use Any():
var shoppingCartSessions = from c in context.ShoppingCartSessions
where c.UserId == gUserID
select c;
if (shoppingCartSessions.Any())
{
//not empty
}
Have you tried checking .Count() > 0 ?
EDIT:
As stated by Mahmoud Gamal, using Any() should render slightly better performance, since it will execute an EXISTS query, rather than a COUNT() on the DB, and you ultimately don't care about the exact amount.

Return one result from LINQ Query

if you have a select LINQ query that should only return one result, do you have to have a foreach loop to get the result?
Or is there a better way?
// Will return a default value if no object is found in the DB
db.Table.SingleOrDefault(x => x.something == someParameter);
or
// Will throw an exception if records are not found
db.Table.Single(x => x.something == someParameter);
Thanks to Mehrdad for the comment...both lines have been updated.
If it's possible that your query could result in more than one record being returned, then (as mentioned in comments) Single() and SingleOrDefault() are the wrong methods to call. You would keep the same syntax, but call First() and FirstOrDefault() respectively.
var myLinqObj = db.MyObjects.Take(1).SingleOrDefault();
You can use either First or Single.
First returns the first row, whether there are multiple rows or just the one.
Single expects only one row to be returned, and throws an exception if there are multiple rows.
Single is therefore potentially a better choice if you expect to only have one row, so that you'll see the problem immediately and can troubleshoot it.
You can just use .First() or .FirstOrDefault() like so:
Foo foo = query.Select(a => a.Name == "foo").FirstOrDefault();
From all the have have said my addition is the use the Value property after you have a single element if you are using LINQ-to-XML.
And the Select new { *cols* } if it a list or array or table.
Example.
... select new {c.Name, c.Value};
This tip is to enable you get the values.

Categories