DataContext LINQ Queries - Should I use my own data object classes? - performance

I apologize if my vocabulary is off on the following question.
I have an SQL Database that has multiple relationships to tables within that database. I've created a DataContext for this database and create a repository of functions used to call it's data.
My question is, because of the relationships (Multiple Linked tables).
Should I create my own class object to hold the results and only grab the needed table's column data like the following:
public IQueryable<VM_userLogs> getUserLogsVM(Nullable<DateTime> startDate, Nullable<DateTime> endDate)
{
if (startDate == null) {
startDate = Convert.ToDateTime("01-01-1900");
}
if (endDate == null) {
endDate = Convert.ToDateTime("01-01-2900");
}
IQueryable<VM_userLogs> logs = from l in ctx.tools_trt_userLogs
where l.timeStamp >= startDate & l.timeStamp <= endDate
select new VM_userLogs {
LOG_ID = l.logId,
NTLOGIN = l.ntLogin,
PRODUCT = l.productName,
SEGMENT = l.segmentName,
PRIORITY = l.priority,
GROUP = l.groupName,
ANSWER = l.answerText,
TIMESTAMP = l.timeStamp,
URL = l.url
};
return logs;
}
or can I just call the underlying object from the datacontext and NOT take a big performance hit... Like the following:
public IQueryable<tools_trt_userLogs> getUserLogs(Nullable<DateTime> startDate, Nullable<DateTime> endDate)
{
if (startDate == null)
{
startDate = Convert.ToDateTime("01-01-1900");
}
if (endDate == null)
{
endDate = Convert.ToDateTime("01-01-2900");
}
IQueryable<tools_trt_userLogs> logs = from l in ctx.tools_trt_userLogs
where l.timeStamp >= startDate & l.timeStamp <= endDate
select l;
return logs;
}

Related

Using custom methods with SQlite.NET Filter predicates

We are using SQLite.NET (1.5.231) in a Xamarin project
We execute Get queries like this
var result = await db.Table<T>().Where(query).ToListAsync();
Where db is a SQLiteAsyncConnection and query is a Expression<Func<T, bool>>
If I pass something like this as query it works
(intervention.EndDate == null && intervention.StartDate == day) ||
intervention.EndDate == null && intervention.StartDate <= day && day <= DateTime.Now.Date
However I'd prefer to wrap the logic up in a function and pass it like this
public async Task<IEnumerable<Intervention>> GetAMonthsInterventionsAsync(int month, int year)
{
var interventions = await this.dataProviderService.GetAsync<Intervention>(
i => ShouldInterventionBeConsideredInMonth(month, year, i),
false);
return interventions;
}
private bool ShouldInterventionBeConsideredInMonth(int month, int year, Intervention intervention)
{
DateTime startOfMonth = new DateTime(year, month, 1).StartOfDay();
DateTime endOfMonth = new DateTime(year, month, DateTime.DaysInMonth(year, month)).EndOfDay();
bool inMonth = false;
if (intervention.StartDate <= endOfMonth && intervention.EndDate != null && intervention.EndDate >= startOfMonth)
{
// Intervention starts before the month ends AND ends after the month starts
inMonth = true;
}
else if (intervention.StartDate <= endOfMonth && intervention.EndDate == null)
{
inMonth = true;
}
if (intervention.IsDeleted)
{
inMonth = false;
}
return inMonth;
}
That fails with a
**System.NotSupportedException:** 'Cannot compile: Parameter'
This is because SQLite cannot understand GetAMonthsInterventionsAsync. How can I use this kind of abstraction with SQlite?

Compare a linq value (int) to an int List using where clause

I have a linq query which joins a couple of tables and returns the value into an object. The query was working fine, till i added a where clause to in. Aftre the where clause, my query returns null.
Here's the code:
List<Int32> resourceSupervisorIdList = new List<Int32>();
resourceSupervisorIdList.Add(searchCriteriaTimesheet.ResourceId);
foreach (resource res in allSubordinateResources)
{
if (!resourceSupervisorIdList.Contains(res.id_resource))
resourceSupervisorIdList.Add(res.id_resource);
}
using (tapEntities te = new tapEntities())
{
var timesheetAll = (from tsh in te.timesheet_header
join rs in te.resources on tsh.id_resource equals rs.id_resource
join tsd in te.timesheet_detail on tsh.id_timesheet equals tsd.id_timesheet
where (resourceSupervisorIdList.Contains(rs.id_resource_supervisor))
select new TimesheetHeaderDetailsItem()
{
OrganizationId = rs.id_organization,
ProjectId = tsd.id_project,
StartDate = tsh.dte_period_start,
EndDate = tsh.dte_period_end,
ApprovedDate = tsh.dte_approved,
RejectedDate = tsh.dte_rejected,
SubmittedDate = tsh.dte_submitted,
});
if (timesheetAll == null || timesheetAll.Count() == 0)
{
return result;
}
}
Now, after adding the where clause, the code runs into the if condition. There are matching records in the table, but still i'm not able to get any records.
rs.id_resource_supervisor
is of type int in the mysql db.

convert Enumerable row collection <short> to short

I have this error can't implicitly convert Enumerable row collection <short> to short in this line of code:
Month = (from item in query select (short)item.Month);
I want to know why and why I can't find distinct() or count method in query variable.
here is my method:
public bool IsEnableAccPosting(
string CompanyCode, DateTime FromDate, DateTime ToDate, out short Month)
{
try
{
o_dmDebitAccounts = new dmDebitAccounts(sysInfo);
bool IsEnable = false;
DataTable dt = o_dmDebitAccounts.GetDebitInterestAccPeriods(CompanyCode);
var query = from data in dt.AsEnumerable()
where data.Field<DateTime>("StartDate") == FromDate &&
data.Field<DateTime>("EndDate") == ToDate
select new
{
Month = Convert.ToInt16(data.Field<short>("Month")),
Year = Convert.ToInt16(data.Field<short>("Year"))
};
Month = (from item in query select (short)item.Month); //heres the error
The field is already typed as an Int16 in the linq query that is performing the operation. You dont need to cast it.
try the following code taken from here
if (query.Any())
{
var result = query.First();
// Console.WriteLine("Results: {0}", result.Month);
Month = result.Month;
}

Dynamically Set Column Name In LINQ Query

Im trying to write a method which will allow me to search different DataTables, over different columns.
So far i have the following:
string selectedValue;
string searchColumn;
string targetColumn;
var results = (from a in dt.AsEnumerable()
where a.Field<string>(searchColumn) == selectedValue
select new
{
targetColumn = a.Field<string>(targetColumn)
}).Distinct();
Which kind of gets the job done, but I'm left with the column name as targetColumn rather than the actual column name I want.
Is there any way to resolve this?
Thanks in advance
CM
I make a LINQ to Datatables
public List<DataRow> Where(this DataTable dt, Func<DataRow, bool> pred)
{
List<DataRow> res = new List<DataRow>();
try {
if (dt != null && dt.Rows.Count > 0) {
for (i = 0; i <= dt.Rows.Count - 1; i++) {
if (pred(dt(i))) {
res.Add(dt(i));
}
}
}
} catch (Exception ex) {
PromptMsg(ex);
}
return res;
}
Usage :
var RowsList = dt.Where(f => f("SomeField").toString() == "SomeValue" ||
f("OtherField") > 5);

Linq to get elements in a list (parent) where a condition is satisfied on property of an object in a child list?

I was wondering if someone could help me in generating a linq query for the following scenario.
Here are the classes with the relevant properties:
public class Employee
{
IList<Employee> DirectReports { get; set;}
IList<BonusPlan> BonusPlans { get; set;}
BonusPlanTemplate BonusPlanTemplate { get; set;}
}
public class BonusPlan
{
FiscalPeriod FiscalPeriod { get; set; }
Employee Employee { get; set;}
}
I'm trying to create a method:
IEnumerable<Employee> GetDirectReportsWithoutBonusPlansCreatedForFiscalPeriod(FiscalPeriod fiscalPeriod)
So basically I have this to get the directreports with bonus plans for a particular fiscal period:
var query = from dr in DirectReports
from bp in dr.BonusPlans
where bp.Employee.BonusPlanTemplate != BonusPlanTemplate.Empty &&
bp.FiscalPeriod==fiscalPeriod
select dr;
IList<Employee> directReportsWithBonusPlansCreated = query.ToList();
Then I get all of the DirectReports that should have bonus plans setup (indicated by having a BonusPlanTemplate assigned) that aren't in the list from the previous query.
var query2 = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
!directReportsWithBonusPlansCreated.Contains(dr)
select dr;
This produces the correct results but it seems like there must be another way. I'm not sure if I need to do this in two steps. Can someone please help me to combine these two linq queries and possibly make it more efficient. I have relatively little experience with Linq.
Do you need the first query for any other reason? If not, it's pretty easy:
var query = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty
&& !dr.BonusPlans.Any(bp => bp.FiscalPeriod == fiscalPeriod)
select dr;
You could make your life easier use an extra method in Employee:
public bool HasBonusPlanForPeriod(FiscalPeriod period)
{
return BonusPlans.Any(bp => bp.FiscalPeriod == fiscalPeriod);
}
Then your original first query becomes:
var query = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
dr.HasBonusPlanForPeriod(fiscalPeriod)
select dr;
IList<Employee> directReportsWithBonusPlansCreated = query.ToList();
and the second query becomes:
var query = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
!dr.HasBonusPlanForPeriod(fiscalPeriod)
select dr;
IList<Employee> directReportsWithBonusPlansCreated = query.ToList();
This is a tricky one...first I thought "Oh it's an outer join...use DefaultIfEmpty". Then I realized you were doing a select many (that's what the two from clauses boil down to). So I did a search for DefaultIfEmpty combined with SelectMany and came up with this gem. Applied to your scenario we get
var query =
from dr in DirectReports
from bp in dr.BonusPlans.DefaultIfEmpty()
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
bp.FiscalPeriod==fiscalPeriod &&
bp==null
select dr;
See if that works for you.

Resources