My query is return not table values - c#

I have FinancialCompliances and Compliance tables. Below my query work flow is get one latest row .The problem is i have empty values in table because i deleted all rows in my table .But my below query is return one old rows .
var Compliance = (from c in datamodel.Compliances
join f in datamodel.FinancialCompliances on c.ComplianceId equals f.ComplianceId
where (c.VerifierId == userId || c.OwnerId == userId || c.UserId == userId) && (f.ComplianceId == c.ComplianceId)
orderby (f.AddedDate)
select f);
financialCompliance = Compliance.ToList().LastOrDefault();
What is the problem?

It sounds like you may be deleting your objects in the datamodel instance but not saving the changes and resetting the datamodel, thereby keeping the old records still in the context even if they aren't in the database. To be safe, try using a new context for this query.
Also, you may want to consider modifying the query to order the results decending and then selecting the top one rather than ordering them ascending and taking only the last one:
var Compliance = (from c in datamodel.Compliances
join f in datamodel.FinancialCompliances on c.ComplianceId equals f.ComplianceId
where (c.VerifierId == userId || c.OwnerId == userId || c.UserId == userId) && (f.ComplianceId == c.ComplianceId)
orderby (f.AddedDate) descending
select f);
financialCompliance = Compliance.FirstOrDefault();

Perhaps lastordefalt are sending the default value. Could you please confirm that you actually have real data in your object that is returned? I doubt that would be the case.

One obvious problem with your code is that you are calling ToList() before LastOrDefault(). This will cause your code to load all data from your storage into your application and context, and then from the result retrieving the last object. I suspect that this may cause some problems.
Try to skip your .ToList() and call LastOrDefault() directly.

Related

Select single dummy row in Entity Framework

I'm trying to do something like this in entity framework.
SELECT (SELECT COUNT(*) FROM Log Where LogTypeId =1) as Log1,
(SELECT COUNT(*) FROM Log Where LogTypeId =2) as Log2
Note the lack of from. In essence, I just want to select a single row that contains aggregation of the Log table. I tried something like this.
(from x in ctx.Logs
select new {
Log1 = ctx.Logs.Count((x) => x.LogTypeId == 1),
Log2 = ctx.Logs.Count((x) => x.LogTypeId == 2)
}).First();
However, this returns a null if ctx.Logs doesn't contain any row (new system, or recently archived). While it's not that difficult check for a null return and simply create a blank entry, I want to know if there's a way to handle it so I don't have to do "If null create a blank aggregate with all field set to 0" everywhere I want to create this query (since I will have several similar style of select in multiple places).
I also want to avoid having to do multiple select, to prevent multiple round trips to the database.
Okay, feel a bit silly and figured out that I can use DefaultIfEmpty.
(from x in ctx.Logs.DefaultIfEmpty()
select new {
Log1 = ctx.Logs.Count((x) => x.LogTypeId == 1),
Log2 = ctx.Logs.Count((x) => x.LogTypeId == 2)
}).First();
To avoid null value you need to use one on the null handling function:
!.nvl
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions105.htm
2.nvl2
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions106.htm
3.coalesce
https://docs.oracle.com/cd/B28359_01/server.111/b28286/functions023.htm#SQLRF00617
Usage:
nvl(yourcolumn,0)
try like this in your code or google for these functions i hope you get some help from my side.

Linq to SQL Slow Query

My ASP.Net application has the following Linq to SQL function to get a distinct list of height values from the product table.
public static List<string> getHeightList(string catID)
{
using (CategoriesClassesDataContext db = new CategoriesClassesDataContext())
{
var heightTable = (from p in db.Products
join cp in db.CatProducts on p.ProductID equals cp.ProductID
where p.Enabled == true && (p.CaseOnly == null || p.CaseOnly == false) && cp.CatID == catID
select new { Height = p.Height, sort = Convert.ToDecimal(p.Height.Replace("\"", "")) }).Distinct().OrderBy(s => s.sort);
List<string> heightList = new List<string>();
foreach (var s in heightTable)
{
heightList.Add(s.Height.ToString());
}
return heightList;
}
}
I ran Redgate SQL Monitor which shows that this query is using a lot of resources.
Redgate is also showing that I am running the following query:
select count(distinct [height]) from product p
join catproduct cp on p.productid = cp.productid
join cat c on cp.catid = c.catid
where p.enabled=1 and p.displayfilter = 1 and c.catid = 'C2-14'
My questions are:
A suggestion to change the function so that it uses less resources?
Also, how does linq to sql generate the above query from my function? (I did not write select count(distinct [height]) from product anywhere in the code)
There are 90,000 records in the products. This category which I am trying to get the distinct list of heights has 50,000 product records
Thank you in advance,
Nick
First of all your posted sql query and linq query doesn't match at all. it's not the LINQ query rather the underlying SQL query itself performing slow. Make sure, all the columns involved in JOIN ON clause and WHERE clause and ORDER BY clause are indexed properly in order to have a better execution plan; else you will end up getting a FULL Table Scan and a File Sort and query will deemed to perform slow.
The join multiplies the number of Products the query returns. To undo that, you apply Distinct at the end. It will certainly reduce db resources if you return unique Products right away:
var heightTable = (from p in db.Products
where p.CatProducts.Any(cp => cp.CatID == catID)
&& p.Enabled && (p.CaseOnly == null || !p.CaseOnly)
select new
{
Height = p.Height,
sort = Convert.ToDecimal(p.Height.Replace("\"", ""))
}).OrderBy(s => s.sort);
This changes the join into a where clause. It saves the db engine the trouble of deduplicating the result.
If that still performs poorly, you should try to do the conversion and ordering in memory, i.e. after receiving the raw results from the database.
As for the count. I don't know where it comes from. Such queries typically get generated by paging libraries such as PagedList, but I see no trace of that in your code.
Side note: you can return ...
heightList.Select(x => x.Height.ToString()).ToList()
... instead of creating the list yourself.

C# LINQ MySQL Query optimisation

Using LINQ to MySQL
MySQL TABLE Definition
ID binary(16) PK
UtcTriggerTime datetime NOT NULL
PersonID binary(16) NOT NULL FK
Status int(11) NOT NULL
I have a array of 1000s of PersonIDs(Guids) and for each of the PersonID I would like to pick matching records from the table with the following criteria:
UtcTriggerTime >= PREDEFINED_DATE_TIME (e.g. UtcNow - 30days)
AND
Status=1 OR Status=2
I am currently using a
foreach(var personID in personIDsArray){
var qryResult = (from a in AlertObjects.AlertsTriggered
where a.PersonID == personID &&
(a.Status == 1 || a.Status == 2) &&
a.UtcTriggerTime >= PREDEFINED_DATE_TIME
select a).ToArray();
}
What are the possible options to optimise this for performance? Or is there?
I tried putting an Index on (UtcTriggerTime, PersonID, Status) and then used the array of PersonIDs to do it in one query as follows, but it was even slower which when I thought about makes sense:
var qryResult = (from a in AlertObjects.AlertsTriggered
where personIDsArray.Contains(a.PersonID) &&
(a.Status == 1 || a.Status == 2) &&
a.UtcTimeTriggered >= PREDEFINED_DATE_TIME
group a by a.PersonID into alerts
select alerts).ToArray();
It seems to me that you are dealing with typical Select N+1 problem which is caused by
group a by a.PersonID into alerts
select alerts
part.
Could you look in the generated SQL and see what it looks like?
Also there is no need to put Status in index if there not many values because the increase on the performance will be minimal.
If my quess is right you can look on these question to see how the problem can be handled:
How to Detect Select n+1 problems in Linq to SQL?
http://www.west-wind.com/weblog/posts/2009/Oct/12/LINQ-to-SQL-Lazy-Loading-and-Prefetching
I'm not familiar with MySql but it seems to me that this link could be helpful in diagnosing which queries are slow.
http://www.electrictoolbox.com/show-running-queries-mysql/

Simple left join in LINQ

I have a Private-Message Table and a User-Table.
I connect them here:
var messageUsers = (from pm in dc.PrivateMessages
join user in dc.Users
on pm.SenderID equals user.UserID
where !pm.IsDeletedRecipient && pm.RecipientID == id
select new PMInbox
{
SenderUsername = user.Username,
PrivateMessageID = pm.PrivateMessageID,
SenderID = pm.SenderID,
Subject = pm.Subject,
Text = pm.Text,
SenderType = pm.SenderType,
IsDeletedRecipient = pm.IsDeletedRecipient,
IsDeletedSender = pm.IsDeletedSender,
IsRead = pm.IsRead,
Timestamp = pm.TimestampSend
}).ToList();
How to make this in a left-join, so if the userID is not the SenderID (e.g. The Sender is deleted allready), the Username should be empty?
var messageUsers = (
from pm in dc.PrivateMessages
where !pm.IsDeletedRecipient && pm.RecipientID == id
select new PMInbox {
SenderUsername = (
from user in dc.Users
where user.UserID == pm.SenderID
select user.Username
).SingleOrDefault(),
PrivateMessageID = pm.PrivateMessageID,
//...
}
).ToList();
In general, to achieve a Left outer join in LINQ, you should be using SingleOrDefault or possibly FirstOrDefault when you wish to include 1 or 0 rows of the joined "table", and DefaultIfEmpty when you may need to include several lines (in my experience, that's a less common occasion, however). In your specific case, it sounds like UserID is a unique identifier for Users - as such, I translated your left join into a SingleOrDefault call rather than a DefaultIfEmpty call.
Unlike SQL, .NET cannot resolve properties on null values. So if you do something like user.Username and user is null, you'll get a NullReferenceException. You can then either check for null every single time you access user, or you can project (i.e. select) before calling SingleOrDefault or DefaultIfEmpty. After all, an empty sequence of users selects an empty sequence of usernames - which, after SingleOrDefault creates a name or null without the need for any manual null-checking.
Do a group join, then unpack the group by querying it. The DefaultIfEmpty generates a null element when the collection is empty.
var messageUsers = (
from pm in dc.PrivateMessages
join u in dc.Users
on pm.SenderID equals u.UserID
into users
from user in users.DefaultIfEmpty()
where !pm.IsDeletedRecipient && pm.RecipientID == id
...
Also, if you have Associations set up between the tables in the dbml, there should be a relational property from PrivateMessage to User that can be used to express the query more simply. (I'm naming that property Senders, but it might be auto-named Users or Users1. You can rename the property in the dbml.)
var messageUsers = (
from pm in dc.PrivateMessages
where !pm.IsDeletedRecipient && pm.RecipientID == id
from user in pm.Senders.DefaultIfEmpty()
...

How to check the null of an embedded linq to entities statement

Using linq to entities i am connecting to a database, the database has tables in it that has payments that have a multi to multi relationship with jobs. This is acheived via an allocs table. I want a list box with all the jobs that has a column called due price which takes all of the allocations of payments for this job and takes that away from the job price. However, using the below linq to entities statement. The problem is that if the job has no allocations it returns null and therefore the due payment is empty. What i really want is for the due payment to be the job price if there are no allocations however, i cannot think of a way around this. Please help before i finally go insane :-(
var jobs = from j in data.jobs
where j.property.customer.id == customerid
&& j.completed != null
select new
{
j.id,
j.price,
dueprice = j.price - ( from a in data.allocs
where a.job.id == j.id
select a.amount ).Sum(),
lineone = j.property.lineone,
postcode = j.property.postcode,
jobtype = j.jobtype.name,
j.completed
};
You can also use the Null Coalescing operator to simplify code like this:
dueprice = j.price - (( from a in data.allocs
where a.job.id == j.id
select a.amount ).Sum() ?? 0)
This operator returns the first value which is not null, so myNum ?? 0 will return myNum if it is not null, and if it is null the operator will return 0.
select a.amount ).Concat(/* array with one zero element */).Sum()
I actually found an answer my self, i will try oleg's as well as it seems to be a little more precise but i thought of doing this
dueprice = j.price - (( from a in data.allocs
where a.job.id == j.id
select a.amount ).Sum())==null ? j.price:
//sets the due price to the normal sum if it has allocs
j.price - ( from a in data.allocs
where a.job.id == j.id
select a.amount ).Sum(),
however i like the idea of only adding on more line of code instead of my several(plus it's repeated code) i will try this and let you all know. Thanks for the response.

Categories