I'm trying to retrieve a few records from a table given a certain condition... this is my code:
var areas = _context.Set<T>()
.Where(p => (int)p.GetType().GetProperty(campoOrdem).GetValue(p) >= indexMin &&
(int)p.GetType().GetProperty(campoOrdem).GetValue(p) <= indexMax).ToList();
I am getting this error :
'The LINQ expression 'DbSet<RH_Cargos>
.Where(r => (int)r.GetType().GetProperty(__campoOrdem_0).GetValue(r) >=
__indexMin_1 && (int)r.GetType().GetProperty(__campoOrdem_0).GetValue(r) <=
__indexMax_2)' could not be translated.
All of my variables are getting the correct values.. campoOrdem is the string which contains the name of the field, indexMin and indexMax is my values of order in the database, in the example, indexMin is 1, and indexMax is 2...
what is happening?
Reflection won't work for what you are trying to do, but if the property always has the same name, you could use generic constraints (if you can add that interface to all relevant entities):
public interface IEntityWithCampoOrdem
{
public int CampoOrdem { get; } // property name should always be the same
}
This assumes that entities like RH_Cargos can be defined like so:
public class RH_Cargos : IEntityWithCampoOrdem
{
// other properties
public int CampoOrdem { get; set; }
}
Now you can create a generic method like so:
public void GetAreas<T>() where T : IEntityWithCampoOrdem
{
var areas = _context.Set<T>()
.Where(p => p.CampoOrdem >= indexMin &&
p.CampoOrdem <= indexMax).ToList();
}
Related
I have an interface like what u see below and I want it to return me a Property Called "ProductionCostId" which has a type of 'int' from a table in the database
int Get(Guid productionLineId, string productionCode)
In the implementation as you can see I want to get this value from a child entity called "ProductionAssignmetnt"
public int Get(Guid productionLineId, string productionCode)
{
return GetAll()
.Where(x => x.ProductionAssignments
.Where(x => x.ProductionLine.Id == productionLineId && x.ProductionCode == productionCode)
.Select(x => x.ProductionCostId);
}
But I dont know how to get this int value
First, you need to include the productionassignments table to this query i.e. join it.
In your GetAll() method where you return in you can join a table using code first by _context.ProductionLines.Include(x => x.ProductionAssignments), if you're on Database First then read this on how to join tables
Now since you haven't posted any model, this is how you'd select if your ProductionCostId is nested inside the assignments
GetAll()
.FirstOrDefault(pLine => pLine.Id == productionLineId)
?.ProductionAssignments.FirstOrDefault(assignment => assignment.ProductionCode == productionCode)?.ProductionCostId)
This query will get the production line with the id, and then select the first productionCostId from the assignments where the code matches. This query assumes the Model
public class ProductionLine
{
public int Id {get;set;}
public List<ProductionAssignment> ProductionAssignments {get;set;}
}
public class ProductionAssignment
{
public int ProductionCode {get;set;}
public int ProductionCostID {get;set;}
public ProductionLine ProductionLine {get;set;}
}
Beware of null reference exceptions.
I am trying to calculate a status based on some threshold variables for a linq to SQL IQueryable Entity.
My entity
contains two properties
public decimal Threshold { get; set; }
public decimal Value{ get; set; }
Now there are other properties for which I am using automapper for projection. Essentially
There is a property for the "response" which takes in the "threshold" and "value" to calculate the "status".
I ended up writing a custom Expression Func.
Expression<Func<EntityModel, string>> GetSeverity(EntityModel entity)
{
var fraction = (double)entity.Value / (double)entity.Threshold;
var red = nameof(Severity.Red);
var amber = nameof(Severity.Amber);
var green = nameof(Severity.Green);
if (fraction > 1)
{
return t => red;
}
if (fraction >= 0.75 && fraction < 1)
{
return t => amber;
}
return t => green;
}
Severity is just an enum.
Now Maybe my usage of a func expression is incorrect
CreateMap<EntityModel, ResponseModel>()
.ForMember(d => d.Severity,e => e.MapFrom(d => GetSeverity(d)));
I end up getting the exception
LINQ to Entities does not recognize the method
'System.String ToString()' method, and this method cannot be translated into a store expression.
Why does this have to be a mapped function? Why not pull down the values needed and then project into a enitity as needed at runtime? Such as (pseudo code)
var currentValues =
MyTable.GetValues()
.ToList() // Gets the values from the db and makes them IEnumerable
.Select(itm => new {
Status = DetermineStatus( … ), // "Red" | "Yellow" ...
itm
}
)
.ToList();
...
private string DetermineStatus(...variables here....);
Or better define a partial class from your model with a new property that returns status as a calculated property?
partial class MyDBItem
{
public string Status { get { return DetermineStatus( … ); } }
}
i struggling to find the correct way to query for a specific entity in my database. I have a table TeamMember which looks as follows:
public class TeamMember
{
public Guid TeamId { get; set; }
public Guid ManagerUserId { get; set; }
...
}
At several positions i want to query for a "TeamManager" in my teams.
public TeamMember GetTeamManager(Guid teamId, List<TeamMember> teamMembers)
{
return teamMembers.FirstOrDefault(member => member.TeamId == teamId && member.ManagerUserId == null);
}
If i want to use a method in an expression e.g (not real code),
...
// IQueryable<TeamMember>
teamMembers.Where(member => member.team.GetTeamManager(teamId, teamMembers))
it works fine for in memory objects, but this does not work in combination with the entity framework, so real db objects.
Therefore i was experimenting with static expressions, but i did not find any solution which uses a static expression in combination with a variable e.g.:
// this should be an ideal solution
Expression<Func<TeamMember, bool>> exp = teammember => teamMember.TeamId == **CUSTOM_VARIABLE** && teamMember.ManagerUserId == null;
teamMembers.Where(exp)
I want to reuse the expression, but i also want to be able to modify the variable. My goal is to avoid the creation of an object in between because the following would work, but is less efficient (correct me if i'm wrong)
teamMembers.ToList().Where(member => member.team.GetTeamManager(teamId, teamMembers))
So please help me with my problem :).
Thank you in advance!
You can't make exp a property because of the need to capture a variable, but you can make it a function returning Expression<Func<TeamMember,bool>>:
Expression<Func<TeamMember,bool>> MakeMemberExpression(Guid teamId) {
return teammember => teamMember.TeamId == teamId && teamMember.ManagerUserId == null;
}
or even
Expression<Func<TeamMember,bool>> MakeMemberExpression(Guid teamId) =>
teammember => teamMember.TeamId == teamId && teamMember.ManagerUserId == null;
You can use it as follows:
var members = teamMembers.Where(MakeMemberExpression(teamId));
You can create a function that operates on IQueryable.
public TeamMember GetTeamManager(IQueryable<TeamMember> baseQuery,Guid teamId)
{
return baseQuery.FirstOrDefault(member => member.TeamId == teamId && member.ManagerUserId == null);
}
When checking that the correct data is being used to call a method I can do this:
mockedClass.Verify(method => method.WriteToConsole(It.Is<Result>(item => item.Name == "Bob" && item.Age == 44)));
where Results is an object that is the output from a Linq query:
public class Result
{
public string Name { get; set; }
public int Age { get; set; }
}
However, I also use IEnumerable as the input to a 2nd method.
How do I amend the Verify above to check that the IEnumerable of Results contains Results I can test against.
mockedClass.Verify(method => method.WriteListToConsole(It.Is<IEnumerable<ResultRecord>>(item => What GOES HERE?)));
"item" at that point is an IEnumerable<ResultRecord>. Just write what you want to test.
Something like this?
mockedClass.Verify(method => method.WriteListToConsole(It.Is<IEnumerable<ResultRecord>>(item => item.Count() == 1 && item.ToList()[0].SomeProperty == "Something")));
I'm trying to accept a Func as a parameter to a function, and then use it both inside and outside a Linq query.
Here, idSelector is a Func of some kind which will return a particular SubLedger id in the Transaction object (e.g. t => t.SubLedger1).
public class Transaction {
public int SubLedger1 { get; set; }
public int SubLedger2 { get; set; }
public int SubLedger3 { get; set; }
public decimal Balance { get; set; }
}
public IEnumerable<Transaction> GetSubLedger(DateTime StartDate, Func<Transaction, int> idSelector) {
// simply returns IQueryable of all
DbSet<Transaction> txns = txnRepo.GetAll();
// get opening balance for each sub ledger
var subLedgers = txns.Where(t => t.Date < StartDate)
.GroupBy(idSelector, t => t, (id, txn) => new { ID = id, Balance = txn.Sum(t => t.Amount) })
.ToDictionary(t => t.ID, t => t.Balance);
// fill running balance
var filtered = txns.Where(t => t.Date >= StartDate).ToList();
foreach (var t in filtered)
{
t.Balance = subLedgers[idSelector.Invoke(t)].Balance += t.Amount;
}
return filtered;
}
I need to use idSelector in two places: first in the Linq query to group all transactions into subLedgers, and second to get the running balance for the particular subledger in the filtered results. I realize that Linq requires an Expression<...> instead, but I can't quite figure out how to Invoke that in the second context.
It's possible I'm going about this the wrong way, is there some other way I should try? This question may also be a little muddled, I did try to pare down the code sample as much as possible, so please ask me if anything is unclear.
Use Compile to get the invokeable method from the expression:
t.Balance = subLedgers[idSelector.Compile()(t)].Balance += t.Amount;
(Assuming idSelector is an Expression<Func<Transaction, int>>.)