EFCore Query and selection - c#

Hey I am trying to query and find a object that looks something like this:
I have already result
I have id that is quiz id.
So i have both Ids.
var singlequiz = await _context.Quizzes
.Include(q => q.Questions)
.ThenInclude(question => question.Options)
.Include(qz => qz.Results)
.Where(b => b.Id == id)
.Select(c => c.Results.Select(z => z.Id == result.Id))
.FirstOrDefaultAsync();
What I am trying to do here is : find an object with id X, then that object with id X has a list of results, I want to get the list, BUT with only the one element that has id of result.Id.
What am i doing wrong?
EDIT:
Used this ATM
var singlequiz = await _context.Quizzes
.Include(x => x.Questions)
.ThenInclude(x => x.Options)
.Include(x => x.Results)
.FirstOrDefaultAsync(x => x.Id == id);
var singleQuizElement = singlequiz.Results.Where(x => x.Id == result.Id).ToList();
singlequiz.Results = singleQuizElement;

Try this :
var singlequiz = await _context.Quizzes
.Include(x => x.Questions)
.ThenInclude(x => x.Options)
.Include(x => x.Results)
.FirstOrDefaultAsync(x=> x.Id == id && x.Results.Any(y => y.Id == result.Id));

Related

Linq variable inside select

I have a following query
return _context.Table1
.Where(x => x.ContactId == contactKey.Id)
.Include(x => x.Table2)
.Include(x => x.Table3.Table4)
.Select(a =>
new MyReadModel
{
PriorityAssignment = true,
LastContactedDate = (a.Table3.Table4 != null && a.Table3.Table4.FirstOrDefault(h =>
h.Id == a.Table2.FkId
) != null ?
a.Table3.Table4.FirstOrDefault(h => && h.Id == a.Table2.FkId
).LastContactedDatetime : default
)
}
)
.ToListAsync();
What i wants is to simplify LastContactedDate assignment with in select. I think we can assign
a.Table3.Table4.FirstOrDefault(h =>
h.Id == a.Table2.FkId
)
to some variable but can't able to do it
can someone identify what is needed
With EF Core you don't have to check for null, LINQ Translator do not execute your code, but uses it for translation to the SQL. Also Includes is not needed if you do not retrieve whole objects.
return await _context.Table1
.Where(x => x.ContactId == contactKey.Id)
.Select(a => new MyReadModel
{
PriorityAssignment = true,
LastContactedDate = (DateTime?)a.Table3.Table4.Where(h => h.Id == a.Table2.FkId)
.OrderByDescending(h => LastContactedDatetime)
.Select(h => LastContactedDatetime)
.FirstOrDefault()
}).ToListAsync();
you can use it like this example
List<string> someList= new List<string>();
someList= someList.Select(x =>
{
var newVariable= "newVariable";
return newVariable;
}).ToList();
in your case
return _context.Table1
.Where(x => x.ContactId == contactKey.Id)
.Include(x => x.Table2)
.Include(x => x.Table3.Table4)
.Select(a => {
Table4 newVariable = null;
if(a.Table3.Table4 != null)
newVariable = a.Table3.Table4.FirstOrDefault(h => h.Id == a.Table2.FkId;
var result = new MyReadModel
{
PriorityAssignment = true,
LastContactedDate = (newVariable != null ? newVariable.LastContactedDatetime : default
)
};
}
) .ToListAsync();

If Else Statement inside entity query

im trying to produce an if else statement inside entity query, i have the following code:
var asset = dbContext.Set<Asset>()
.Include(x => x.Item)
.Include(x => x.Item.ItemDetailSubCategory)
.Include(x => x.AssetCurrentStatus)
.Include(x => x.AssetCurrentStatus.AssetCondition)
.Include(x => x.Currency)
.Include(x => x.AssetCurrentStatus.AssetAccessories)
.Where(x => x.AssetCurrentStatus.Room.Floor.IsActive == true)
.Where(x => x.AssetCurrentStatus.Room.Floor.Building.IsActive == true)
.Where(x => x.AssetCurrentStatus.Room.IsActive == true)
.ToList();
now i expect something like :
var asset = dbContext.Set<Asset>()
.Include(x => x.Item)
.Include(x => x.Item.ItemDetailSubCategory)
.Include(x => x.AssetCurrentStatus)
.Include(x => x.AssetCurrentStatus.AssetCondition)
.Include(x => x.Currency)
.Include(x => x.AssetCurrentStatus.AssetAccessories)
if(x.AssetCurrentStatus.AssetLocation != null)
{
.Where(x => x.AssetCurrentStatus.Room.Floor.IsActive == true)
.Where(x => x.AssetCurrentStatus.Room.Floor.Building.IsActive == true)
.Where(x => x.AssetCurrentStatus.Room.IsActive == true)
}
else
{
.ToList()
}
is there any way to achieve this?
thanks in advance
Well, an if doesn't make sense because you want to apply that logic on every asset not only once. So you need to apply it to the query itself:
var asset = dbContext.Set<Asset>()
.Include(....)
.Where(x => x.AssetCurrentStatus.AssetLocation == null
|| (x.AssetCurrentStatus.Room.Floor.IsActive
&& x.AssetCurrentStatus.Room.Floor.Building.IsActive
&& x.AssetCurrentStatus.Room.IsActive))
.ToList();
Consecutive && are the same as consecutive Where.
You can try this
var asset = dbContext.Set<Asset>()
.Include(x => x.Item)
.Include(x => x.Item.ItemDetailSubCategory)
.Include(x => x.AssetCurrentStatus)
.Include(x => x.AssetCurrentStatus.AssetCondition)
.Include(x => x.Currency)
.Include(x => x.AssetCurrentStatus.AssetAccessories)
.Where(x => x.AssetCurrentStatus.AssetLocation != null ?
x.AssetCurrentStatus.Room.Floor.IsActive == true && x.AssetCurrentStatus.Room.Floor.Building.IsActive == true && x.AssetCurrentStatus.Room.IsActive == true :
true).ToList();

C# Linq Lambda for group by multiple columns select max

I want to translate this into lambda syntax and can't seem to get it to work:
Grouping by two columns, select max on a different column, return list of complete complex object.
I am writing more text here to get past the validation on this form. How much text is needed until I am allowed to post this?
_clientpolicies = (from policy in
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
group policy by
new
{
PolicyReference = GetPolicyReference(policy),
PolicyType = policy.ProductInformation.PolicyTypeCode
}
into g
let maxPolicyInception = g.Max(p => p.InceptionDate)
from policyGroup in g
where policyGroup.InceptionDate == maxPolicyInception
select policyGroup).ToList();
I dont think there's a way of doing it in one line. So there's my try :
policyGroups=
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm
.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
.GroupBy(x => GetPolicyReference(x))
.ThenBy(x => x.ProductInformation.PolicyTypeCode)
.ToList();
var maxPolicyInception = policyGroups.Max(p => p.InceptionDate);
_clientpolicies = policyGroups
.Where(g => g.InceptionDate == maxPolicyInception)
.ToList();
_clientpolicies =
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
.GroupBy(x =>
new
{
PolicyReference = GetPolicyReference(x),
PolicyType = x.ProductInformation.PolicyTypeCode
},
(key, g) => g.OrderByDescending(gx => gx.InceptionDate).First()

Linq query fine tuning

Query logic is Grouping the items by Id and Ordering it by Id. Then inside grouped items Ordering by Item1 then by Item2.
Linq query below,
var group1Items = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code = 1)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
var group2Items = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code = 2)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
MyList.Clear();
MyList.InsertRange(Mylist.Count, group1Items);
MyList.InsertRange(Mylist.Count, group2Items);
In the above two queries, only difference is Where condition. Is it possible to rewrite into single query?
Single query:
var groupItems = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == 1 || a.Code == 2)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
If Code 1 must come before Code 2:
var groupItems = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == 1)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items)
.Union(MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == 2)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items)).ToList();
If you only want to avoid code duplication it may be easiest to capture a variable holding the code by which to filter.
int code = 0; // initialize with any value
var groupItems = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == code)
.Select(s => new
{
key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
})
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items); // No ToList() here!
MyList.Clear();
code = 1;
MyList.InsertRange(Mylist.Count, groupItems.ToList());
code = 2;
MyList.InsertRange(Mylist.Count, groupItems.ToList());
Removed where clause in the LINQ expression and implemented at InsertRange() method. This avoids redundant queries
var groupItems = MyList
.GroupBy(g => g.Id)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
MyList.Clear();
MyList.InsertRange(Mylist.Count, groupItems.Where(w => w.Code == 1));
MyList.InsertRange(Mylist.Count, groupItems.Where(w => w.Code == 2));

Get one child element per group

I am getting, with EF6, one advert by position as follows:
var adverts = context.Adverts
.Include(x => x.Files)
.Where(x => x.Position <= 32)
.OrderBy(x => Guid.NewGuid())
.GroupBy(x => x.Position)
.ToDictionary(x => x.Key, x => x.First());
I get one advert per group and each advert has one file.
But what I really want is a file for each advert so I tried:
var adverts = context.Adverts
.Include(x => x.Files)
.Where(x => x.Position <= 32)
.OrderBy(x => Guid.NewGuid())
.GroupBy(x => x.Position)
.ToDictionary(x => x.Key, x => x.First().Files);
In this case the value of the dictionary is empty.
Any idea how to solve this?

Categories

Resources