get count in linq query - c#

i want to get count in linq query its work fine without comparing date in where condition but after comparing date it gives exception.
public static IList GetAllCategoryData()
{
using (var objEntity = new BlueCouponEntities())
{
return (from TBL in objEntity.CategoryMasters.AsEnumerable()
let IIT = TBL.CategoryImageTransactions
select new
{
TBL.CategoryID,
TBL.CategoryName,
CategoryCount = objEntity.OfferCategoryMasters.Where(Lg => Lg.CategoryID == TBL.CategoryID && Lg.OfferMaster.EndDate > DateTime.Now.Date).Count(),
}
).ToList();
}
}
Error is : The specified type member ;Date; is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

You have to use EntityFunctions.TruncateTime to get the Date part of DateTime
using (var objEntity = new BlueCouponEntities())
{
return (from TBL in objEntity.CategoryMasters.AsEnumerable()
let IIT = TBL.CategoryImageTransactions
select new
{
TBL.CategoryID,
TBL.CategoryName,
CategoryCount = objEntity.OfferCategoryMasters.Where(Lg => Lg.CategoryID == TBL.CategoryID && Lg.OfferMaster.EndDate > EntityFunctions.TruncateTime(DateTime.Now)).Count(),
}
).ToList();
}
Since DateTime.Now is Constant at the moment, you could also write this
using (var objEntity = new BlueCouponEntities())
{
DateTime now = DateTime.Now.Date;
return (from TBL in objEntity.CategoryMasters.AsEnumerable()
let IIT = TBL.CategoryImageTransactions
select new
{
TBL.CategoryID,
TBL.CategoryName,
CategoryCount = objEntity.OfferCategoryMasters.Where(Lg => Lg.CategoryID == TBL.CategoryID && Lg.OfferMaster.EndDate > now).Count(),
}
).ToList();
}

It has nothing to do with the Count() function. As the exception says, its
a DateTime problem. Use DbFunctions.TruncateTime (EntityFunctions.TruncateTime is deprecated since EF6)
public static IList GetAllCategoryData()
{
using (var objEntity = new BlueCouponEntities())
{
return (from TBL in objEntity.CategoryMasters.AsEnumerable()
let IIT = TBL.CategoryImageTransactions
select new
{
TBL.CategoryID,
TBL.CategoryName,
CategoryCount = objEntity.OfferCategoryMasters.Where(Lg => Lg.CategoryID == TBL.CategoryID && EntityFunctions.TruncateTime(Lg.OfferMaster.EndDate) > EntityFunctions.TruncateTime(DateTime.Now.Date)).Count(),
}
).ToList();
}
}

Add following lines:
var today = DateTime.Now.Date;
Then use today instead of DateTime.Now.Date into linq query.

Related

Linq Expression Query with In clause [duplicate]

This question already has answers here:
Linq to Entities - SQL "IN" clause
(9 answers)
Closed 8 years ago.
How to make a where in clause similar to one in SQL Server?
I made one by myself but can anyone please improve this?
public List<State> Wherein(string listofcountrycodes)
{
string[] countrycode = null;
countrycode = listofcountrycodes.Split(',');
List<State> statelist = new List<State>();
for (int i = 0; i < countrycode.Length; i++)
{
_states.AddRange(
from states in _objdatasources.StateList()
where states.CountryCode == countrycode[i].ToString()
select new State
{
StateName = states.StateName
});
}
return _states;
}
This expression should do what you want to achieve.
dataSource.StateList.Where(s => countryCodes.Contains(s.CountryCode))
This will translate to a where in clause in Linq to SQL...
var myInClause = new string[] {"One", "Two", "Three"};
var results = from x in MyTable
where myInClause.Contains(x.SomeColumn)
select x;
// OR
var results = MyTable.Where(x => myInClause.Contains(x.SomeColumn));
In the case of your query, you could do something like this...
var results = from states in _objectdatasource.StateList()
where listofcountrycodes.Contains(states.CountryCode)
select new State
{
StateName = states.StateName
};
// OR
var results = _objectdatasource.StateList()
.Where(s => listofcountrycodes.Contains(s.CountryCode))
.Select(s => new State { StateName = s.StateName});
I like it as an extension method:
public static bool In<T>(this T source, params T[] list)
{
return list.Contains(source);
}
Now you call:
var states = _objdatasources.StateList().Where(s => s.In(countrycodes));
You can pass individual values too:
var states = tooManyStates.Where(s => s.In("x", "y", "z"));
Feels more natural and closer to sql.
public List<Requirement> listInquiryLogged()
{
using (DataClassesDataContext dt = new DataClassesDataContext(System.Configuration.ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString))
{
var inq = new int[] {1683,1684,1685,1686,1687,1688,1688,1689,1690,1691,1692,1693};
var result = from Q in dt.Requirements
where inq.Contains(Q.ID)
orderby Q.Description
select Q;
return result.ToList<Requirement>();
}
}
The "IN" clause is built into linq via the .Contains() method.
For example, to get all People whose .States's are "NY" or "FL":
using (DataContext dc = new DataContext("connectionstring"))
{
List<string> states = new List<string>(){"NY", "FL"};
List<Person> list = (from p in dc.GetTable<Person>() where states.Contains(p.State) select p).ToList();
}
from state in _objedatasource.StateList()
where listofcountrycodes.Contains(state.CountryCode)
select state
This little bit different idea. But it will useful to you. I have used sub query to inside the linq main query.
Problem:
Let say we have document table. Schema as follows
schema : document(name,version,auther,modifieddate)
composite Keys : name,version
So we need to get latest versions of all documents.
soloution
var result = (from t in Context.document
where ((from tt in Context.document where t.Name == tt.Name
orderby tt.Version descending select new {Vesion=tt.Version}).FirstOrDefault()).Vesion.Contains(t.Version)
select t).ToList();
public List<State> GetcountryCodeStates(List<string> countryCodes)
{
List<State> states = new List<State>();
states = (from a in _objdatasources.StateList.AsEnumerable()
where countryCodes.Any(c => c.Contains(a.CountryCode))
select a).ToList();
return states;
}

LinqToDb: Rank is server-side method

I am trying to use linq2db.EntityFrameworkCore for some of its windowing functions, such as RANK().
Below is my implementation:
var abc = (from tl in _repo.Context.TransferLink
join tlt in _repo.Context.TransferLinkType on new { TLinkId = tl.TransferLinkTypeId, EType = "Deviance" } equals new { TLinkId = tlt.TransferLinkTypeId, EType = tlt.EnumTransferLinkType }
//let duplicateCount = _repo.Context.TransferLink.Where(tl1 => tl1.SecondaryTransferId != null && tl.SecondaryTransferId != null &&
//tl1.SecondaryTransferId == tl.SecondaryTransferId.Value).Count()
where
(allTransferIds.Contains(tl.PrimaryTransferId) || allTransferIds.Contains(tl.SecondaryTransferId)) &&
!tl.Archived
select new
{
TransferLinkId = tl.TransferLinkId,
TransferLinktypeId = tl.TransferLinkTypeId,
PrimaryTransferId = tl.PrimaryTransferId,
SecondaryTransferId = tl.SecondaryTransferId,
DuplicateCount = Sql.Ext.Count(tl.TransferLinkId)
.Over()
.PartitionBy(tl.SecondaryTransferId)
.ToValue()
UpdatedDate = tl.UpdatedDate,
RankVal = Sql.Ext.Rank()
.Over()
.PartitionBy(tl.TransferLinkTypeId, tl.SecondaryTransferId)
.OrderByDesc(tl.UpdatedDate)
.ThenBy(tl.TransferLinkId)
.ToValue()
}).ToList();
This code throws the exception:
Rank is server-side method
I have tried searching for a solution, but could not find any.
Any idea?
For using linq2db.EntityFrameworkCore you have to switch to library's LINQ provider. It can be done by simple ToLinqToDB() call.
var query = /* some EF Core query */
query = query.ToLinqToDB();
var result = query.ToList();

LINQ Dynamic Query with group by and string variable

I want to create a dynamic query with LINQ-to-SQL and everything works except for one thing: group by. I looked at the other questions but haven't found a reason so far why it does not work.
I use using System.Linq.Dynamic; with the following query (that works):
int numberOfRankedItems = 3;
string minMaxChoice = "max";
string orderBy = "";
if (minMaxChoice == "max")
{
orderBy = "queryGroup.Sum(row => row.POSITIONVALUE) descending";
} else if (minMaxChoice == "min")
{
orderBy = "queryGroup.Sum(row => row.POSITIONVALUE) ascending";
}
string minMaxFeatureColumnName = "BRANDNAME";
string selectMinMaxFeature = "new { minMaxFeature = queryGroup.Key." + minMaxFeatureColumnName + ", sumPosition = queryGroup.Sum(row => row.POSITIONVALUE)}";
var query = (from tableRow in Context.xxx
where /* some filters */
group tableRow by tableRow.BRANDNAME into queryGroup
orderby orderBy
select selectMinMaxFeature).Take(numberOfRankedItems).ToList();
The use of variables for orderby and select works fine, but for group by not no matter what I try to replace with a variable. The query actually works if I e.g. use a variable instead of tableRow.BRANDNAME but the query returns the wrong result. The goal is to be able to set the column for the grouping dynamically.
Ideas?
Thanks
Edit: there seem to be multiple issues also with the other variables. So I generalize the question a bit: how can I generalize the following query in terms of
The column to group by
The column to order by + ASC or DESC
In the select statement the columnname of the first statement (BRANDNAME)
Here is the query:
var query = (from tableRow in ctx.xxx
where /* filter */
group tableRow by new { tableRow.BRANDNAME } into queryGroup
orderby queryGroup.Sum(row => row.POSITIONVALUE) descending
select new { minMaxFeature = queryGroup.Key.BRANDNAME, sumPosition = queryGroup.Sum(row => row.POSITIONVALUE) }).Take(numberOfRankedItems).ToList();
Would be great without expression trees ;)
I have now elaborated a solution to the question:
The solution uses as before using System.Linq.Dynamic; allows now to set certain variables. In the end it returns a dictionary.
// set variables
int numberOfRankedItems;
if (queryData.NumberOfRankedItems != null)
{
numberOfRankedItems = (int) queryData.NumberOfRankedItems;
} else
{
numberOfRankedItems = 0;
}
string minMaxChoice = queryData.MinMaxChoice;
string minMaxFeatureColumnName = queryData.MinMaxFeatureColumnName;
string orderByPrompt = "";
if (minMaxChoice == "max")
{
orderByPrompt = "it.Sum(POSITIONVALUE) descending";
} else if (minMaxChoice == "min")
{
orderByPrompt = "it.Sum(POSITIONVALUE) ascending";
}
string groupByPrompt = queryData.MinMaxFeatureColumnName;
// execute query
IQueryable query = (from tableRow in Context.xxx
where /* some filters */
select tableRow).
GroupBy(groupByPrompt, "it").
OrderBy(orderByPrompt).
Select("new (it.Key as minMaxFeature, it.Sum(POSITIONVALUE) as sumPosition)").
Take(numberOfRankedItems);
// create response dictionary
Dictionary<int?, Dictionary<string, int?>> response = new Dictionary<int?, Dictionary<string, int?>>();
int count = 1;
foreach (dynamic item in query)
{
string minMaxFeatureReturn = item.GetType().GetProperty("minMaxFeature").GetValue(item);
int? sumPositionReturn = item.GetType().GetProperty("sumPosition").GetValue(item);
response[count] = new Dictionary<string, int?>() { { minMaxFeatureReturn, sumPositionReturn } };
count++;
}
return response;

How to solve error in LINQ: Data is null or empty

I have the following code. I want to check if the result is null with an if condition but it always shows an error. How to solve this?
string StrRefNo = Request.QueryString["ref"];
string[] SMSid = StrRefNo.Split('$');
DownloadsDbEntities db = new DownloadsDbEntities();
var data = (from d in db.SMSLink_Expiry
where d.RefNo == SMSid[0]
&& d.SMSLink.ID == Convert.ToInt32(SMSid[1])
select d).ToList();
if (data.Count > 0)
{
string ss = "yes";
}
The LINQ expression node type 'ArrayIndex' is not supported in LINQ to Entities.
Since the expression can not be translated into SQL, pull it out of the statement
string SMSId0 = SMSid[0];
int SMSId1 = Convert.ToInt32(SMSid[1]);
var data = (from d in db.SMSLink_Expiry
where d.RefNo == SMSId0
&& d.SMSLink.ID == SMSId1
select d).ToList();
This should fix your problem:
string StrRefNo = Request.QueryString["ref"];
string[] SMSid = StrRefNo.Split('$');
var ref = SMSid[0];
var smsLinkId = Convert.ToInt32(SMSid[1]);
DownloadsDbEntities db = new DownloadsDbEntities();
var data = (from d in db.SMSLink_Expiry
where d.RefNo == ref
&& d.SMSLink.ID == smsLinkId
select d).ToList();
if (data.Count > 0)
{
string ss="yes";
}
There are many things Linq does not support, since its translating the query to SQL internally.
For reference: The LINQ expression node type 'ArrayIndex' is not supported in LINQ to Entities
You can try this :
string[] SMSid = StrRefNo.Split('$');
var refno=SMSid[0];
var id=Convert.ToInt32(SMSid[1];
DownloadsDbEntities db = new DownloadsDbEntities();
var data = (from d in db.SMSLink_Expiry
where d.RefNo == refno
&& d.SMSLink.ID == id)
select d).ToList();

Replace foreach to make loop into queryable

I have a function returning a report object, but currently i am going through a foreach look and then using the asQueryable method.
I would like to do it in one query and not have to use the AsQueryable function.
var query = from item in context.Dealers
where item.ManufacturerId == manufacturerId
select item;
IList<DealerReport> list = new List<DealerReport>();
foreach (var deal in query)
{
foreach (var bodyshop in deal.Bodyshops1.Where(x => x.Manufacturer2Bodyshop.Select(s => s.ManufacturerId).Contains(manufacturerId)))
{
DealerReport report = new DealerReport();
report.Dealer = deal.Name;
report.Bodyshop = bodyshop.Name;
short stat = bodyshop.Manufacturer2Bodyshop.FirstOrDefault(x => x.ManufacturerId == manufacturerId).ComplianceStatus;
report.StatusShort = stat;
list.Add(report);
}
}
return list.OrderBy(x => x.Dealer).AsQueryable();
I think you want something like this:
var query = from deal in context.Dealers
where deal.ManufacturerId == manufacturerId
from bodyshop in deal.Bodyshops1
where bodyshop.Manufacturer2Bodyshop.Select(s => s.ManufacturerId).Contains(manufacturerId)
let stat = bodyshop.Manufacturer2Bodyshop.FirstOrDefault(x => x.ManufacturerId == manufacturerId)
orderby deal.Name
select new DealerReport
{
Dealer = deal.Name,
Bodyshop = bodyshop.Name,
StatusShort = stat != null ? stat.ComplianceStatus : 0, // or some other default
};
return query;

Categories

Resources