How do I convert SQL Query to Lambda? - c#

I have the following SQL query that returns the results I need:
SELECT
STAFF_ID
FROM [dbo].[StaffTable]
WHERE STAFF_ID NOT IN (SELECT STAFF_ID
FROM [dbo].[StaffingTable]
WHERE [DATE] = #DATE
AND MODEL_ID = #Model)
I have the following controller method to try and return the correct results:
public JsonResult GetStaffResults(DateTime date, string modelId)
{
Guid modelGuid = Guid.Parse(modelId);
var settings = new JsonSerializerSettings();
var staff = context.StaffTable.Select(c => new
{
Id = c.StaffId,
Name = c.StaffName
});
var staffing = context.StaffingTable.Select(c => new
{
modelId = c.ModelId,
manufacturerId = c.ManufacturerId,
staffId = c.StaffId,
date = c.Date,
recordId = c.RecordId
});
var staffResults = staff.Where(p => staffing.Select(o => o.modelId).First() == modelGuid && !staffing.Select(o => o.date).Contains(date));
return Json(shiftResults, settings);
}
However, I'm struggling with the Lambda expression, it returns no results so I've missed something somewhere.

You can try something like this:
public JsonResult GetStaffResults(DateTime date, string modelId)
{
Guid modelGuid = Guid.Parse(modelId);
var settings = new JsonSerializerSettings();
var staffQuery = context.StaffTable
.Where(s => !context
.StaffingTable
.Any(st => st.StaffId = s.StaffId && st.modelId == modelGuid && st.date == date))
.Select(c => new
{
Id = c.StaffId,
Name = c.StaffName
});
return Json(staffQuery.ToList(), settings);
}

You are doing separate query with Select which has a performance issue as the queries will return IEnumerable<T> objects. If you want to have separate queries then try to get the query results as IQueryable<T> which will construct the queries and will load data at the end.
For example:
var query =
from st in context.StaffTable
where !(from stff in context.StaffingTable
select stff.CustomerID)
where stff.MODEL_ID = ModelIdVariable AND stff.DATE = DATEVariable
.Contains(st.CustomerID)
select st;
Declare and populate the ModelIdVariable and DATEVariable variables before the query.
Then you can do query.ToList<T>() where you need the data to be loaded.

Related

LINQ to Objects - Reduce repetition - Map inside select statement

I am using LINQ to objects to run the multiple queries like below, I want to retain a separate method for each of the queries below but I want to have a function to map inside the select statement.
GetDTOCourseListActiveCourses
GetDTOCourseListWithValidDates
GetDTOCourseListRequirePayments
With each I am currently doing a manual mapping exercise inside the select for each query like below:
public IList<DTOCourse> GetDTOCourseListActiveCourses()
{
var query = _UoW.tblcoursRepo.All.Where(c => c.IsActive == true);
IList<DTOCourse> courselist = new List<DTOCourse>();
courselist = query.Select(x => new DTOCourse
{
////// BUT, I want to create a function here to do the mapping //
courseId = x.CourseID,
courseTitle = x.CourseTitle,
mainHeading = x.MainHeading.description,
courseType = x.ListType.description,
courseStatus = x.ListStatus.description,
orgId = x.OrgID.Value
}).ToList();
return courselist;
}
I have created the following method to map to the DTO class, this works fine when converting a single instance:
public DTOCourse MaptblcourseToDTOCourse(tblcours course)
{
DTOCourse dto = new DTOCourse
{
courseId = course.CourseID,
courseTitle = course.CourseTitle,
mainHeading = course.MainHeading.description,
courseType = course.ListType.description,
courseStatus = course.ListStatus.description,
orgId = course.OrgID.Value
};
return dto;
}
How can I combine this method to map within a select? I'm looking for something like below:
public IList<DTOCourse> GetDTOCourseListActiveCourses()
{
var query = _UoW.tblcoursRepo.All.Where(c => c.IsActive == true);
IList<DTOCourse> courselist = new List<DTOCourse>();
courselist = query.Select(x => new DTOCourse
{
MaptblcoursToDTOCourse(x)
}).ToList();
return courselist;
}
You are almost there. You can call your mapping method in your Select call like this:
courselist = query.Select(x => MaptblcoursToDTOCourse(x)).ToList();
Or even shorter:
courselist = query.Select(MaptblcoursToDTOCourse).ToList();

How can I compare a value from List<string> to Project.Models.Class?

I want to retrieve data from Project.Models.transaction_details by using linq, comparing value from list of string (List).
here is my code
List<transaction_details> transactions = new List<transaction_details>();
List<string> date_list = new List<string>();
// date_list output is ["2020-01-01","2020-01-02",2020-01-03",...,"2020-01-31"]
while (sdr.Read())
{
transactions.Add(new transaction_details
{
ID = sdr.GetInt32("ID"),
Transdate = sdr.GetDateTime("Transdate"),
Debit = sdr.GetDecimal("Debit"),
TransactionName =sdr.GetString("TransactionName"),
BranchID = sdr.GetString("BranchID")
});
}
var array1Index = date_list.Select((i, index) => new { Index = index, i = i }).ToList();
List<transaction_details> arrayresult = new List<transaction_details>();
var query1 = from a in array1Index
select transactions.Contains(a.i) == true ? a.i : "";
arrayresult = query1.ToList();
arrayresult.ForEach(x => {
Console.Write(x + " ");
});
My problem is (a.i) is an error.
Cannot convert 'string' to 'Project.Models.transaction_details'.
you probably mean to check the transaction date. try this:
var query1 = from a in array1Index
select transactions.Any(t => t.Transdate == a.i) == true ? a.i : "";
EDIT:
if you want a list of transactions try this:
var query1 = from t in transactions
where array1Index.Any(a => a.i == t.Transdate)
select t;
var query1 = from t in transactions
where array1Index.Any(a => a.i == t.Transdate);
try this

EF: How to pass column name dynamically to where clause

i am not before dev pc. i just started working with EF. so curious to know can we pass column name dynamically for where clause.
see a screen shot for searching grid.
i just compose a sample query. please tell me does it work?
public ActionResult Index(String ColumnName,String SearchText)
{
private CustomersEntities db = new CustomersEntities();
var customer = (from s in db.Customers
select new CustomerDTO
{
CustomerID = s.CustomerID,
CompanyName = s.CompanyName,
ContactName = s.ContactName,
ContactTitle = s.ContactTitle,
Address = s.Address
})
.Where(s => s.Field<string>(ColumnName).ToUpper().Contains(SearchText.ToUpper());
return View(customer);
}
thanks
public ActionResult Index(string ColumnName, string SearchText)
{
var arg = Expression.Parameter(typeof(Customer), "x");
var strType = typeof(string);
var ToUpperMeth = strType.GetMethods().Where(x => x.Name == nameof(string.ToUpper)
&& x.GetParameters().Count() == 0).Single();
var ContainsMeth = strType.GetMethods().Where(x => x.Name == nameof(string.Contains)
&& x.GetParameters().Count() == 1).Single();
var exprVal = Expression.Constant(SearchText);
var toUpExprVal = Expression.Call(exprVal, ToUpperMeth);
var exprProp = Expression.Property(arg, ColumnName);
var toUpExpr = Expression.Call(exprProp, ToUpperMeth);
var contExpr = Expression.Call(toUpExpr, ContainsMeth, toUpExprVal);
var predicate = Expression.Lambda<Func<Customer, bool>>(contExpr, arg);
var customer = (from s in db.Customers
select new CustomerDTO
{
CustomerID = s.CustomerID,
CompanyName = s.CompanyName,
ContactName = s.ContactName,
ContactTitle = s.ContactTitle,
Address = s.Address
}).Where(predicate).ToList();
return View(customer);
}
You can create something like this in repository (if you use it)
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return _context.Set<CustomersEntities>().Where(predicate);
}
and then
var result = _repository.FindBy(y => y.CompanyName.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0);
The basic pattern is to build up the query at runtime, selectively adding Where expressions before running the query and projecting the results into the DTO.
Like this:
public IList<CustomerDTO> FindCustomers(String ColumnName, String SearchText)
{
var query = from s in db.Customers select s;
if (ColumnName == "CompanyName")
{
query = query.Where(c => c.CompanyName == SearchText);
}
else if (ColumnName == "ContactName")
{
query = query.Where(c => c.ContactName == SearchText);
}
//. . .
else
{
throw new InvalidOperationException($"Column {ColumnName} not found or not supported for searching.");
}
var results = from c in query
select new CustomerDTO()
{
CustomerID = c.CustomerID,
CompanyName = c.CompanyName,
ContactName = c.ContactName,
ContactTitle = c.ContactTitle,
Address = c.Address
};
return results;
}

How to return list of object which associated with one ID?

I am still getting familiar with SQL and LINQ and I am trying to get every objects and its objects which is under one ID.
The below is the EDMX Diagram.
I am passing ClientID and I want to list everything that is under that ClientID and the below is my query to do so but as you can see query is only returning the first element but how to change it to return the list of every elements as below:
Passed ClientID
THeaderTitle 1
TReportName 1
TReportName 2
MY query is below which is returning the first element:
public TReportHeaderModel GetHeadersByClient(int ClientID)
{
using (var connection = new TReportEntitiesConnection())
{
var query = (from c in connection.THeader.Include("TReports")
where
c.ClientID == ClientID
select new TReportHeaderModel()
{
ID = c.ID,
THeaderTitle = c.THeaderTitle,
RowNumber = c.RowNumber,
TReports = (from t in c.TReports
select new TReportModel()
{
ID = t.ID,
TReportName = t.TReportName,
URL = t.URL,
RowNumber = t.RowNumber
}).ToList()
}).First();
return query;
}
}
I've got it working!
I had to change it in my interface as
IList GetHeadersByClient (int ClientID);
So that I can return List of elements in my controller to pass to view.
public IList<TReportHeaderModel> GetHeadersByClient(int ClientID)
{
using (var connection = new TReportEntitiesConnection())
{
var query = (from c in connection.THeader.Include("TReports")
where
c.ClientID == ClientID
select new TReportHeaderModel()
{
ID = c.ID,
THeaderTitle = c.THeaderTitle,
RowNumber = c.RowNumber,
TReports = (from t in c.TReports
select new TReportModel()
{
ID = t.ID,
TReportName = t.TReportName,
URL = t.URL,
RowNumber = t.RowNumber
}).ToList()
});
return query.ToList();
}
}

Cannot implicitly convert type 'System.Collections.Generic.List<AnonymousType#1>' to 'System.Collections.Generic.IList

I'm try to use "GROUP BY" im MVC
This is my function
private readonly ICacheManager _cacheManager;
public virtual IList<ShippingByWeightRecord> GetAll()
{
string key = SHIPPINGBYWEIGHT_ALL_KEY;
return _cacheManager.Get(key, () =>
{
var query = from sbw in _sbwRepository.Table
group sbw by new
{
sbw.ShippingMethodId,
sbw.From,
sbw.To,
sbw.ShippingChargeAmount,
sbw.RegionId,
sbw.ItemRangeId
}
into grouping
select new { grouping.Key,
Id = grouping.Max(sbw => sbw.Id)
};
var records = query.ToList();
return records;
});
}
But there is error. How to do it??
This is my sql Command.
SELECT MIN(Id) AS id, ShippingMethodId, [From], [To], ShippingChargeAmount, RegionId, ItemRangeId
FROM ShippingByWeight
GROUP BY ShippingMethodId, [From], [To], ShippingChargeAmount, RegionId, ItemRangeId
I want to write it in MVC?
Do you have any idea???
You need to create instance of ShippingByWeightRecord in select. Should be:
var query = from sbw in _sbwRepository.Table
group sbw by new
{
sbw.ShippingMethodId,
sbw.From,
sbw.To,
sbw.ShippingChargeAmount,
sbw.RegionId,
sbw.ItemRangeId
}
into grouping
select new ShippingByWeightRecord {
Id = grouping.Max(sbw => sbw.Id),
ShippingMethodId = grouping.Key.ShippingMethodId,
From = grouping.Key.From,
To = grouping.Key.To,
ShippingChargeAmount = grouping.Key.ShippingChargeAmount,
RegionId = grouping.Key.RegionId,
ItemRangeId = grouping.Key.ItemRangeId
};

Categories

Resources