Is there a way to set this entity/linq query to IEnumerable? - c#

I'm trying to return an IEnumerable activities instead of "var"
var activities = ctx.Activities.Where(a => a.SiteID == propID)
.Where(a => a.ActivityTypeName == "Call")
.Select(x => new
{
x.DateTimeEntry,
x.Contact.OwnerContact.ParcelDatas
.FirstOrDefault(a => a.OwnerContactID == x.Contact.OwnerContact.OOwnerID)
.Parcel_LetterTracking.LMailDate,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID)
.FAQ_Library.FaqNum,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID)
.FAQ_Library.Question
});
edit: data type Object compiles but I'm not sure if that's right.

.Select already returns a an IEnumerable<TResult> also combine your ..where() clauses with && instead. https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=netframework-4.8 also one other thing you can do is use .AsEnuemerable()
var activities = ctx.Activities.Where(a => a.SiteID == propID && a.ActivityTypeName == "Call")
.Select(x => new
{
x.DateTimeEntry,
x.Contact.OwnerContact.ParcelDatas.FirstOrDefault(a => a.OwnerContactID == x.Contact.OwnerContact.OOwnerID).Parcel_LetterTracking.LMailDate,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.FaqNum,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.Question
}).AsEnumerable();

Related

Linq complex queries C#

i have this:
int item = particleEdges.ElementAt(i).Key;
Point3 hashPoint = particleEdges[item][j].hashEdge;
var hashList = particleEdges
.Where(p => p.Value.Any(q => q.hashEdge == hashPoint))
.Select(r => r.Key != item)
.ToList();
How to exclude "item" from hashList? Broke my head. Linq doesn't want to open to me.
var hashList = particleEdges
.Where(p => p.Value.Any(q => q.hashEdge == hashPoint))
.Where(r => r.Key != item)
.Select(s => s.Key)
.ToList();

LINQ Query if condition external parameter

I'm trying to use LINQ to get a list of values.
I have code like this:
var _context = _scope.ServiceProvider.GetRequiredService<VMContext>();
if (boolparameter)
{
var listCE = _context.Ce
.Where(x => x.VuId == element.VuId)
.Where(x => x.Score == 8)
.AsNoTracking()
.ToList();
}
else
{
var listCE = _context.Ce
.Where(x => x.VuId == element.VuId)
.AsNoTracking()
.ToList();
}
Depends on boolparameter, I do a query or another one. Is there a way to use a single query with a conditions inside?
Something like:
var listCE = _context.Ce
.Where(x => x.VuId == element.VuId)
.Where(x => boolparameter ? x.Score == 8 : true)
.AsNoTracking()
.ToList();
C# Asp.NetCore SqlServer 2019
Thanks a lot!
You could try the following code if it works:
var listCE = _context.Ce
.Where(x => x.VuId == element.VuId)
.Where(x => !boolparameter || x.Score == 8)
.AsNoTracking()
.ToList();
Which means if boolparameter is false, x.Score doesn't matter, since !false would equal to true and it satisfies OR condition. Likewise if boolparameter is true, then x.score will also be checked if it is equal to 8.
Or maybe with one Where condition:
var listCE = _context.Ce
.Where(x => x.VuId == element.VuId && (!boolparameter || x.Score == 8))
.AsNoTracking()
.ToList();
var listCE = _context.Ce
.Where(x =>
x.VuId == element.VuId
&& (!boolparameter || x.Score == 8))
.AsNoTracking()
.ToList();
This checks whether boolparameter is true before checking x.Score.
Can you check that below?
var listCE = _context.Ce
.Where(x => boolparameter == false ? x.VuId == element.VuId :
(x.VuId == element.VuId &&
x.Score == 8))
.AsNoTracking()
.ToList();
This way is more verbose, but if you have more (or complicated) conditions it can be easier to read and quickly understand what affects the query.
LINQ doesn't execute the query until you reach .ToList() or otherwise try to access the result from the query.
This means you don't need to have the full query duplicated in both the if and else part:
var _context = _scope.ServiceProvider.GetRequiredService<VMContext>();
var listCEQuery = _context.Ce.Where(x => x.VuId == element.VuId)
// LINQ will append this to the initial where clause
if (boolparameter == true)
listCEQuery = listCEQuery.Where(x => x.Score == 8)
var listCE = listCEQuery.AsNoTracking().ToList();

Two dbcontexts cause an error "value cannot be null. parameter name entitytype"

I have 2 DbContexts in my application, and need to do a join in 2 tables that are each one in a different DbContext; I get this error
value cannot be null. parameter name entitytype
When I try to join 2 tables of the same context, this error does not happen.
var VerificaExistenciaSinistro = sinistroContext.SnsAviso
.Join(
sinistroContext.SnsNumAviso,
sinistro => sinistro.NumApo,
aviso => aviso.NumApo,
(sinistro, aviso) => new {
sinistroV = sinistro,
avisoV = aviso })
.Where(c => c.sinistroV.CodItm == c.avisoV.CodItm &&
c.sinistroV.NumApo == c.avisoV.NumApo &&
c.sinistroV.NumAvs == c.avisoV.SeqNumAvs)
.Join(sgsContext.EmsEmissao,
sinistro1 => sinistro1.sinistroV.CodCtrtAvs,
emissao => emissao.CodCtrt,
(sinistro1, emissao) => new {
sinistroC = sinistro1,
emissaoC = emissao })
.Where(c => c.sinistroC.sinistroV.CodCtrtAvs == c.emissaoC.CodCtrt &&
c.emissaoC.CodEmis == c.sinistroC.avisoV.CodEms)
.Where(x => x.sinistroC.sinistroV.NumApo == apolice &&
x.emissaoC.StsEmis == emissao &&
x.emissaoC.NumEndosso ==endosso &&
x.sinistroC.sinistroV.CodItm == cod_itm &&
x.sinistroC.sinistroV.CodCbe == cbeCod)
.Select(x => x.sinistroC)
.ToList();
It generally occurs when u query data from two dbcontext using IQueryable
I encountered the same issue when I was using two dbContext. The solution which I found was. If u are using join between two tables then load any one table's data first to a variable/Object so that It becomes IEnumerable or IList and then do join with that variable/Object to the another table of another dbContext
Example
var FirstDbContextTable = sinistroContext.SnsAviso
.Join(
sinistroContext.SnsNumAviso,
sinistro => sinistro.NumApo,
aviso => aviso.NumApo,
(sinistro, aviso) => new {
sinistroV = sinistro,
avisoV = aviso })
.Where(c => c.sinistroV.CodItm == c.avisoV.CodItm &&
c.sinistroV.NumApo == c.avisoV.NumApo &&
c.sinistroV.NumAvs == c.avisoV.SeqNumAvs).ToList();
var result=FirstDbContextTable.Join(sgsContext.EmsEmissao,
sinistro1 => sinistro1.sinistroV.CodCtrtAvs,
emissao => emissao.CodCtrt,
(sinistro1, emissao) => new {
sinistroC = sinistro1,
emissaoC = emissao })
.Where(c => c.sinistroC.sinistroV.CodCtrtAvs == c.emissaoC.CodCtrt &&
c.emissaoC.CodEmis == c.sinistroC.avisoV.CodEms)
.Where(x => x.sinistroC.sinistroV.NumApo == apolice &&
x.emissaoC.StsEmis == emissao &&
x.emissaoC.NumEndosso ==endosso &&
x.sinistroC.sinistroV.CodItm == cod_itm &&
x.sinistroC.sinistroV.CodCbe == cbeCod)
.Select(x => x.sinistroC)
.ToList();

LINQ error: System.NotSupportedException on GroupBy Selection

When var items = q3.ToList(); executes from the code snippet below, it throws exception System.NotSupportedException. The aim is to get the list of items after the grouping.
Exception:
Unable to create a constant value of type 'AppDB.Stage.Rules'. Only primitive types or enumeration types are supported in this context.
var valuations = context.stage
.Where(q => q.stageID == stageID && !rules.ToList().Any(r => r.type1 == q.type1 || r.type2 == q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
var q3 = valuations.Select(y => new StageType
{
TypeKey = y.Key,
TypeName= "UNKNOWN",
});
var items = q3.ToList(); //error here
Your database doesn't have any idea of what your in-memory rules actually is, and in-turn cant convert this statement to SQL
The simplest solution will be to leave it as an IQueryable and don't use ToList,
context.stage
.Where(q => q.stageID == stageID && !rules.Any(r => r.type1 == q.type1 || r.type2 == q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
However, if it is already in memory, then you will have to send the values as a primitive list
var type1s = rules.Select(x => x.type1);
var type2s = rules.Select(x => x.type2);
context.stage
.Where(q => q.stageID == stageID && !type1s.Contains(q.type1) && !type2s.Contains(q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
Because rules.ToList() makes results in memory, you can't use it inside an IQueryable that executes over SQL. You should first bring your data into memory and then narrow it by other in-memory object.
var valuations = context.stage.ToList()
.Where(q => q.stageID == stageID && !rules.ToList().Any(r => r.type1 == q.type1 || r.type2 == q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
var q3 = valuations.Select(y => new StageType
{
TypeKey = y.Key,
TypeName= "UNKNOWN",
});
var items = q3.ToList();

I'm getting an error when trying to join against multiple tables in a query

I getting this error when I join:
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: The specified LINQ expression contains references to queries that are associated with different contexts.
var rightsList = RoleRightService.GetRoleRights<RoleRight>().Where(x => x.RoleCode == role && x.CompanyId == USER_OBJECT.CompanyId).AsEnumerable();
var securables = SecurableServices.GetSecurable<Securable>()
.GroupBy(a => new { a.RegistrationType_LookUpId })
.Select(r => new
{
id = r.Select(x => x.SecurableID),
registrationType = r.Key.RegistrationType_LookUpId,
RegistrationTypeName = r.Select(x => x.RegistrationType.LookUpDescription).Distinct().FirstOrDefault(),
IsChecked = false,
pageList = r.GroupBy(b => new { b.PageID })
.Select(p => new SecurableViewModel
{
Id = p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.SecurableID).FirstOrDefault(),
PageId = p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.PageID).FirstOrDefault(),
PageName = p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.PageDescription).FirstOrDefault(),// && rr.AccessRight !=0
IsChecked = rightsList.Where(rr => rr.SecurableID == (p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.SecurableID).FirstOrDefault())).Count() > 0,
operationList = r.Where(x => x.PageID == p.Key.PageID && x.Type == 2)
.Select(o => new RoleRightViewModel
{
Id = o.SecurableID,
OperationID = o.OperationID,
OperationName = o.OperationDescription,
IsChecked = rightsList.Where(rr => rr.SecurableID == o.SecurableID).Count() > 0,
})
.ToList()
}).ToList()
}).ToList();
I am getting error
The specified LINQ expression contains references to queries that are associated with different contexts.
For this line:
IsChecked = rightsList.Where(rr => rr.SecurableID == (p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.SecurableID).FirstOrDefault())).Count() > 0,
is there possibilty to right delegate for this
It looks like you are using multiple EF entity contexts, possibly to query more than one database. EF is not able to perform a linq to entities query across more than one EF context.
In order to execute this query without error is will be necessary to use linq to objects instead by projecting the data from each context into memory before combining them. Please note this may have a negative performance impact since all objects will need to be fetched into memory before being filtered down.
Try adding a .ToList() between your GroupBy and Select statements:
var securables = SecurableServices.GetSecurable<Securable>()
.GroupBy(a => new { a.RegistrationType_LookUpId })
.ToList()
.Select(r => new
...

Categories