Running NbLinksExpirationStatus takes about 12 seconds to execute, which is not fast enough for what i am trying to achieve. Could it be Contains() problem and is there any way i can make it execute faster? i am working with EF6 and Sql Server. Please let me know if also in this case it is better to just use sqlquery instead or not?
NOTE :
HashSet<int> oneEntitiesPerimeter = oneEquipment.Select(x => x.ID_ONE).ToHashSet();
HashSet<int> twoEntitiesPerimeter = twoEquipment.Select(x => x.ID_TWO).ToHashSet();
The method where there is the query :
public static Tuple<int, int> NbLinksExpirationStatus(HashSet<int> oneEntitiesPerimeter, HashSet<int> twoEntitiesPerimeter)
{
using (DbEntities context = new DbEntities())
{
int aboutToExpireValue = Constants.LinkStatusAboutToExpire; #1
int expiredValue = Constants.LinkStatusExpired; #2
var oneIds = oneEntitiesPerimeter ?? new HashSet<int>();
var twoIds = twoEntitiesPerimeter ?? new HashSet<int>();
var joinedQuery = (from t in context.ONE_DISTRIBUTION_STATUS
join o in context.TWO_DISTRIBUTION_STATUS on t.ID_ent equals o.ID_ent into joined
from o in joined.DefaultIfEmpty()
where oneIds.Contains(t.ID_ONE) && (o == null || twoIds.Contains(o.ID_TWO))
select new { oneExpirationStatus = t.LINK_STATUS_EXPIRATION, twoExpirationStatus = o.LINK_STATUS_EXPIRATION }).ToList();
var aboutToExpireCount = joinedQuery.Where(j =>
j.oneExpirationStatus == aboutToExpireValue || j.twoExpirationStatus == aboutToExpireValue).Count();
var expiredCount = joinedQuery.Where(j =>
j.oneExpirationStatus == expiredValue || j.twoExpirationStatus == expiredValue).Count();
return new Tuple<int, int>(aboutToExpireCount, expiredCount);
}
}
EDIT: i have tried to use SQL instead but the speed of the execution is always not improving. This is the attempt :
string oneIds = "NULL";
if(oneEntitiesPerimeter != null && oneEntitiesPerimeter.Count > 0)
{
oneIds = string.Join(",", oneEntitiesPerimeter);
}
string twoIds = "NULL";
if (twoEntitiesPerimeter != null && twoEntitiesPerimeter.Count > 0)
{
twoIds = string.Join(",", twoEntitiesPerimeter);
}
string sqlQuery = "SELECT " +
"COALESCE(SUM(CASE WHEN t.LINK_STATUS_EXPIRATION = " + aboutToExpireValue + " OR COALESCE(o.LINK_STATUS_EXPIRATION, '')= " + aboutToExpireValue + " THEN 1 ELSE 0 END), 0) AS AboutToExpire," +
"COALESCE(SUM(CASE WHEN t.LINK_STATUS_EXPIRATION = " + expiredValue + " OR COALESCE(o.LINK_STATUS_EXPIRATION, '') = " + expiredValue + " THEN 1 ELSE 0 END), 0) AS Expired "+
"FROM ONE_DISTRIBUTION_STATUS t LEFT JOIN TWO_DISTRIBUTION_STATUS o ON t.ID_ent = o.ID_ent WHERE t.ID_ONE in (" + oneIds + ") AND (o.ID_TWO in (" + twoIds + ") OR o.ID_TWO IS NULL)";
var counter = context.Database.SqlQuery<LinkExpirationStatusWidget>(sqlQuery).FirstOrDefault();
result = new Tuple<int, int>(counter.AboutToExpire, counter.Expired);
The class added to store results :
public class LinkExpirationStatusWidget
{
/// <summary>
/// Gets or sets count of links about to expire
/// </summary>
/// <value>About To Expire count</value>
public int AboutToExpire { get; set; }
/// <summary>
/// Gets or sets count of links expired
/// </summary>
/// <value>Expired count</value>
public int Expired { get; set; }
}
NbLinksExpirationStatusexecytes at least 2 very complicated queries based onjoinedQuery, the part that shouldn't be done by hand. It seems like those 2 queries could be replaced by aGroupByclause ononeExpirationStatusandtwoExpirationStatus. Apart from that, there's no way to say why each of the 2 queries is slow - are there missing indexes? Too much data?it is better to use SQLno, it's better to understand what EF is actually doing and how to use it. If you have aCustomerentity with aCustomer.Ordersproperty, you don't need JOINs. If you wanted to count specific order and customer statuses statuses by customer you could writecontext.Orders.Where(ord=>ordIds.Contains(ord.Status) && custIds.Contains(ord.Customer.Status)).GroupBy(o=>new {OrderStatus=o.Status,CustomerStatus=o.Customer.Status}).Select(g=>new {g.Key,Count=g.Count());joinedQuerypart has aToList()way out to the right. Without anyGroupBythough that returns all combinations instead of returning a count for each combination