I am using a string sql query because of performance issues with using Linq. Due to a lot of outer applies, and a lot of where clauses using IN. The code in this sample is reduced for clarity here. I left off the IF-ELSE statements that added (or not) a lot of code to the where clause.
Here is my business object, it has an IEnumerable as a property.
public class AssetBO
{
public Guid AssetId { get; set; }
public Guid SiteId { get; set; }
public string Name { get; set; }
public IEnumerable<AssetDivisionBO> AssetDivisionInfo { get; set; }
}
And here is my string sql:
string SQL_Data = #"SELECT DISTINCT e.AssetId, e.SiteId, e.Name
FROM
Asset.vAssetLinkBox e
OUTER APPLY (
SELECT
ld.AssetDivisionId,
ld.SiteId,
ld.AssetId,
ld.DivisionId,
ld.IsDeleted,
ld.Created,
ld.LastModified,
ld.ModifiedByEmployeeId,
ld.CreatedByEmployeeId,
FROM Asset.AssetDivision ld
WHERE
ld.IsDeleted = 0
AND ld.AssetId = e.AssetId
) AS AssetDivisionInfo
WHERE
e.IsDeleted = 0";
I then run this:
var query = context.Database.SqlQuery<AssetBO>(SQL_Data);
List<AssetBO> assets = query.ToList<AssetBO>();
I would like to populate the IEnumerable AssetDivisionInfo, from the OUTER APPLY in the string SQL. Is this possible?
I get my AssetBO object, and the AssetDivisionInfo is null. Is there a way to map it?
EDIT: I was asked to supply the original Linq, so posting it here now. I need all of those OUTER APPLIES returned with the data.
public static List<ModuleView.AssetBO> Asset_GetList_ByRadFilter(COG_ContextDB context, RadFilter filter, string where_clause,
Guid Base_ContextSiteId, Guid Base_ContextEmployeeId, HashSet<Guid> PassedAssetIdList,
bool Base_ContextEmployee_IsForAllDivisions,
int PageNumber, int PageSize, string OrderByField, bool IsDescending,
bool IsRestrictedByDivision, HashSet<Guid?> Employee_DivisionIdList, out int RecordCount)
{
var interceptor = new Common.BLL.CommandInterceptorHelper();
System.Data.Entity.Infrastructure.Interception.DbInterception.Add(interceptor);
HashSet<Guid> IsForAll_AssetIdList = new HashSet<Guid>();
if (IsRestrictedByDivision == true)
{
//db hit, so calling only if IsRestrictedByDivision == true
IsForAll_AssetIdList = GetIsForAllDivisions_Assets(context, Base_ContextSiteId);
}
else
{
Base_ContextEmployee_IsForAllDivisions = false;
}
var query = from e in context.vAssetLinkBoxes
from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()
//OUTER APPLY to get a list of AssetIds from AssetDivision table, that are in the employees DivisionIdList (divisions he has access to.) DEV-3504
let AssetIdList = (from dv in context.AssetDivisions.Where(div => div.AssetId == e.AssetId && div.IsDeleted == false && Employee_DivisionIdList.Contains(div.DivisionId)) select dv.AssetId).ToList<Guid>()
join assetUsageInfo in
(
from e in context.AssetUsages
from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()
where e.IsDeleted == false
select new ModuleView.AssetUsageBO
{
AssetUsageId = e.AssetUsageId,
SiteId = e.SiteId,
AssetId = e.AssetId,
AssetUsageTypeId = e.AssetUsageTypeId,
ImportId = e.ImportId,
IsDeleted = e.IsDeleted,
Created = e.Created,
LastModified = e.LastModified,
ModifiedByEmployeeId = e.ModifiedByEmployeeId,
CreatedByEmployeeId = e.CreatedByEmployeeId,
CreatedByEmployeeName = (!string.IsNullOrEmpty(cbu.FirstName)) ? cbu.LastName + ", " + cbu.FirstName : cbu.LastName,
IsDirty = false,
IsNew = false,
}
) on e.AssetId equals assetUsageInfo.AssetId into assetUsageInfos
join assetExtendedFieldInfo in
(
from e in context.AssetExtendedFields
from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()
where e.IsDeleted == false
orderby e.FieldName
select new ModuleView.AssetExtendedFieldBO
{
AssetExtendedFieldId = e.AssetExtendedFieldId,
SiteId = e.SiteId,
AssetId = e.AssetId,
FieldName = e.FieldName,
FieldLabel = e.FieldLabel,
FieldValue = e.FieldValue,
FieldDataType = e.FieldDataType,
IsDeleted = e.IsDeleted,
Created = e.Created,
LastModified = e.LastModified,
ModifiedByEmployeeId = e.ModifiedByEmployeeId,
CreatedByEmployeeId = e.CreatedByEmployeeId,
CreatedByEmployeeName = (!string.IsNullOrEmpty(cbu.FirstName)) ? cbu.LastName + ", " + cbu.FirstName : cbu.LastName,
IsDirty = false,
IsNew = false,
}
) on e.AssetId equals assetExtendedFieldInfo.AssetId into assetExtendedFieldInfos
join assetDivisionInfo in
(
from e in context.AssetDivisions
from d in context.Divisions.Where(emp => emp.DivisionId == e.DivisionId && emp.IsDeleted == false)
from a in context.Assets.Where(emp => emp.AssetId == e.AssetId && emp.IsDeleted == false)
from cbu in context.Employees.Where(emp => emp.EmployeeId == e.CreatedByEmployeeId && emp.IsDeleted == false).DefaultIfEmpty()
where e.IsDeleted == false
select new ModuleView.AssetDivisionBO
{
AssetDivisionId = e.AssetDivisionId,
SiteId = e.SiteId,
AssetId = e.AssetId,
DivisionId = e.DivisionId,
IsDeleted = e.IsDeleted,
Created = e.Created,
LastModified = e.LastModified,
ModifiedByEmployeeId = e.ModifiedByEmployeeId,
CreatedByEmployeeId = e.CreatedByEmployeeId,
CreatedByEmployeeName = (!string.IsNullOrEmpty(cbu.FirstName)) ? cbu.LastName + ", " + cbu.FirstName : cbu.LastName,
DivisionName = d.DivisionName,
AssetName = a.Name,
IsDirty = false,
IsNew = false,
}
) on e.AssetId equals assetDivisionInfo.AssetId into assetDivisionInfos
where e.SiteId == Base_ContextSiteId
&& (IsRestrictedByDivision == false || (IsRestrictedByDivision == true && (Base_ContextEmployee_IsForAllDivisions == true || AssetIdList.Contains(e.AssetId) || IsForAll_AssetIdList.Contains(e.AssetId)))) //from outer apply
select new ModuleView.AssetBO
{
AssetId = e.AssetId,
SiteId = e.SiteId,
AssetTypeId = e.AssetTypeId,
Name = e.Name,
Description = e.Description,
UniqueIdentity = e.UniqueIdentity,
StatusId = e.StatusId,
CompanyId = e.CompanyId,
Make = e.Make,
Model = e.Model,
Year = e.Year,
SerialNumber = e.SerialNumber,
PhoneNumber = e.PhoneNumber,
Email = e.Email,
IsActive = e.IsActive,
BlockedTimeIsEnabled = e.BlockedTimeIsEnabled,
ImportId = e.ImportId,
IsForAllDivisions = e.IsForAllDivisions,
IsDeleted = e.IsDeleted,
Created = e.Created,
LastModified = e.LastModified,
ModifiedByEmployeeId = e.ModifiedByEmployeeId,
AssetTypeName = e.AssetTypeName,
StatusName = e.StatusName,
CompanyName = e.CompanyName,
ModifiedByEmployeeName = e.ModifiedByEmployeeName,
AssetUsageTypeId = e.AssetUsageTypeId,
NumCaptainsOnBoard = (e.CaptainNum == null) ? 0 : (int)e.CaptainNum,
ActivityTimeInMin = e.TotalDurationInMin,
AssetUsageInfo = assetUsageInfos,
CreatedByEmployeeId = e.CreatedByEmployeeId,
CreatedByEmployeeName = (!string.IsNullOrEmpty(cbu.FirstName)) ? cbu.LastName + ", " + cbu.FirstName : cbu.LastName,
AssetExtendedFieldInfo = assetExtendedFieldInfos,
AssetDivisionInfo = assetDivisionInfos,
DivisionDelimitedString = "", //must be here to avoid error when sorting. Sort is done in BA code.
};
if (string.IsNullOrEmpty(where_clause))
{
where_clause = DataFilterBA.GetFilterWhereClause(context, filter, "ASSET", Base_ContextEmployeeId, Base_ContextSiteId, "LINQ");
}
int SkipRows = (PageNumber - 1) * PageSize;
if (PassedAssetIdList.Count == 0)
{
RecordCount = query.Where(where_clause).Select(d => d.AssetId).Distinct().Count();
//RecordCount = query.Where(where_clause).GroupBy(test => test.AssetId)
// .Select(grp => grp.FirstOrDefault()).Count();
query = query.Where(where_clause).OrderBy(OrderByField + (IsDescending ? " descending" : ""));
}
else
{
RecordCount = query.Where(x => PassedAssetIdList.Contains(x.AssetId)).Where(where_clause).Select(d => d.AssetId).Distinct().Count();
query = query.Where(x => PassedAssetIdList.Contains(x.AssetId)).Where(where_clause).OrderBy(OrderByField + (IsDescending ? " descending" : ""));
}
List<ModuleView.AssetBO> items = new List<ModuleView.AssetBO>();
if (PageSize == -1)
{
items = query.ToList<ModuleView.AssetBO>();
}
else
{
items = query.Skip(SkipRows).Take(PageSize).ToList<ModuleView.AssetBO>();
}
System.Data.Entity.Infrastructure.Interception.DbInterception.Remove(interceptor);
if (items != null && items.Count > 0)
{
items = items.GroupBy(test => test.AssetId)
.Select(grp => grp.FirstOrDefault())
.ToList();
return items;
}
return new List<ModuleView.AssetBO>();
}
I have one page which contains one multiple partial pages. In each partial view there will be again multiple partial pages. When I am getting this, it will add data table to ds contains three tables. How can I show it in hierarchical order?
In my ds three tables come from DB shows particular record. How can I display this?
THis is my DAL:
public static ConsignmentNote GetConsignmentNoteByID(int id)
{
ConsignmentNote consignmentnote = null;
SqlConnection sqlConnection = null;
sqlConnection = SqlConnectionHelper.GetConnectionConnectionString();
SqlCommand cmd = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
try
{
cmd = new SqlCommand("GetConsignmentNoteByCNNoteId", sqlConnection);
cmd.Parameters.Add(new SqlParameter("#ConsignmentNoteID", id));
cmd.CommandType = CommandType.StoredProcedure;
da.SelectCommand = cmd;
da.Fill(ds);
//First table data
if (ds.Tables[0].Rows.Count > 0)
{
DataRow row = ds.Tables[0].Rows[0];
consignmentnote = new ConsignmentNote(row);
}
else
{
consignmentnote = new ConsignmentNote();
}
//Second table data
consignmentnote.LstAdditionalCN = new List<AdditionalCN>();
int rowIndexCN = 1;
if (ds.Tables[1].Rows.Count > 0)
{
int i = 0;
foreach (DataRow acnRow in ds.Tables[i].Rows)
{
AdditionalCN objACN = new AdditionalCN();
objACN.ConsignmentNoteRelID = acnRow["ConsignmentNoteRelID"] as Int32? ?? 0;
objACN.ConsignmentNoteID = acnRow["ConsignmentNoteID"] as Int32? ?? 0;
objACN.ConsignmentNoteNumber = acnRow["ConsignmentNoteNumber"] as string ?? null;
objACN.CNDate = acnRow["CNDate"] as DateTime? ?? DateTime.MinValue;
objACN.ConsignerID = (acnRow["ConsignerID"] as Int32? ?? 0).ToString();
objACN.ConsigneeID = (acnRow["ConsigneeID"] as Int32? ?? 0).ToString();
objACN.LocationFrom = acnRow["LocationFrom"] as string ?? null;
objACN.LocationTo = acnRow["LocationTo"] as string ?? null;
if (rowIndexCN == 1)
{
//insert to default CNI
consignmentnote.ConsignmentNoteRelID = objACN.ConsignmentNoteRelID;
consignmentnote.ConsignmentNoteNumber = objACN.ConsignmentNoteNumber;
}
else
{
//insert to additional CNI
consignmentnote.LstAdditionalCN.Add(objACN);
}
rowIndexCN++;
}
}
consignmentnote.LstAdditionalInvoice = new List<AdditionalInvoice>();
int rowIndexCNInvoice = 1;
if (ds.Tables[2].Rows.Count > 0)
{
foreach (DataRow acnRow in ds.Tables[2].Rows)
{
AdditionalInvoice objACN = new AdditionalInvoice();
objACN.ConsignmentNoteLineItemID = acnRow["ConsignmentNoteLineItemID"] as Int32? ?? 0;
objACN.ConsignmentNoteID = acnRow["ConsignmentNoteID"] as Int32? ?? 0;
objACN.ConsignmentNoteRelID = acnRow["ConsignmentNoteRelID"] as Int32? ?? 0;
objACN.ProjectPO = (acnRow["ProjectPO"] as Int32? ?? 0).ToString();
objACN.InvoiceNum = (acnRow["InvoiceNum"] as Int32? ?? 0).ToString();
objACN.InvoiceDate = acnRow["InvoiceDate"] as DateTime? ?? DateTime.MinValue;
objACN.Pkgs = acnRow["Pkgs"] as string ?? null;
objACN.Description = acnRow["Description"] as string ?? null;
objACN.ActualWeight = acnRow["ActualWeight"] as string ?? null;
objACN.ChargedWeight = acnRow["ChargedWeight"] as string ?? null;
objACN.InvoiceValue = acnRow["InvoiceValue"] as decimal? ?? 0;
if (rowIndexCNInvoice == 1)
{
//insert to default CNI
consignmentnote.ConsignmentNoteRelID = objACN.ConsignmentNoteRelID;
consignmentnote.ConsignmentNoteID = objACN.ConsignmentNoteID;
}
else
{
//insert to additional CNI
consignmentnote.LstAdditionalInvoice.Add(objACN);
}
rowIndexCNInvoice++;
}
}
}
catch (Exception x)
{
throw x;
}
finally
{
}
return consignmentnote;
}
I am using this code for authorization on controllers.
with [Authorize(Policy = "CustomRole")]
The thing happened that after 3 or 4 request it fails with
A second operation started on this context before a previous operation completed
public class CustomRoleRequirement : AuthorizationHandler<CustomRoleRequirement>, IAuthorizationRequirement
{
public CMSContext _context = new CMSContext();
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRoleRequirement requirement)
{
var routeobj = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;
var c = routeobj.RouteData.Values.Values.ToList();
var keys = routeobj.RouteData.Values.Keys.ToList();
string area = "";
string id = "";
string controller = "";
string action = "";
string module = "";
foreach (var item in keys)
{
if (item=="area")
{
int indexs = keys.FindIndex(cc => cc == "area");
area = c[indexs].ToString();
}
else if (item == "id")
{
int indexs = keys.FindIndex(cc => cc == "id");
id = c[indexs].ToString();
}
else if (item == "controller")
{
int indexs = keys.FindIndex(cc => cc == "controller");
controller = c[indexs].ToString();
}
else if (item == "module")
{
int indexs = keys.FindIndex(cc => cc == "module");
module = c[indexs].ToString();
}
else if (item == "action")
{
int indexs = keys.FindIndex(cc => cc == "action");
action = c[indexs].ToString();
}
}
string modulelink = controller;
if (!string.IsNullOrEmpty(module))
{
modulelink = modulelink + "/" + module;
}
List<string> Roles = new List<string>();
int UserId = Auth.UserID;
string UserName = Auth.UserName;
if (UserName == "superadmin")
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
// apparently the error occurred here
var moduleobj = _context.AppModules.FirstOrDefault(q => q.Link == modulelink);
if (moduleobj != null)
{ // 69 role is assessing news module
//60 role is accessing page module
var RolesModulesobj = _context.AppRolesModules.FirstOrDefault(q => q.ModuleId == moduleobj.ModuleId && q.RolesId == Auth.RoleId);
if (RolesModulesobj != null)
{
string permissionsobj = RolesModulesobj.Permissions;
List<string> PermissionsListobj = permissionsobj.Split(',').Select(x => x.Trim()).ToList();
var FindFullAccess = PermissionsListobj.FirstOrDefault(q => q.Contains("FullAccess:true"));
if (FindFullAccess != null)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
var abc = PermissionsListobj.FirstOrDefault(q => q.Contains(action + ":true"));
if (abc != null)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
context.Fail();
return Task.CompletedTask;
}
}
}
}
}
The error occurred at this line above
var moduleobj = _context.AppModules.FirstOrDefault(q => q.Link == modulelink);
How can I make task wait before the second operation started in the method above?
You can't use a singleton DB context. You either create one each time you need one or you pool them.
I am trying to 'convert' a query to List while using async to retrieve the values to a list and return the NewsListViewModel to my controller as a success or failure like so:
var model = await db.News.Where(n => n.newsPublished == false
&& n.newsTitle.Contains(query)
|| n.newsDescription.Contains(query)).
OrderBy(n => n.newsCreatedDate).Select(n => new List<NewsListViewModel>
{
NewsCreatorFName = n.Profile.profileFirstName,
NewsCreatorLName = n.Profile.profileLastName,
NewsID = n.newsID,
NewsCreatorID = n.userID,
NewsTitle = n.newsTitle,
CreatedDate = n.newsCreatedDate
})
.ToListAsync();
or like this:
public static async Task<List<NewsListViewModel>> GetAllNotPublished(string query)
{
if (query != "" && query != null)
{
var model = (from n in db.News
where n.newsPublished == false && n.newsTitle.Contains(query)
|| n.newsDescription.Contains(query)
orderby n.newsCreatedDate
select new NewsListViewModel
{
NewsCreatorFName = n.Profile.profileFirstName,
NewsCreatorLName = n.Profile.profileLastName,
NewsID = n.newsID,
NewsCreatorID = n.userID,
NewsTitle = n.newsTitle,
CreatedDate = n.newsCreatedDate
});
return await model.ToListAsync();
}
else
{
var model = (from n in db.News
where n.newsPublished == false
orderby n.newsCreatedDate
select new NewsListViewModel
{
NewsCreatorFName = n.Profile.profileFirstName,
NewsCreatorLName = n.Profile.profileLastName,
NewsID = n.newsID,
NewsCreatorID = n.userID,
NewsTitle = n.newsTitle,
CreatedDate = n.newsCreatedDate
});
return await model.ToListAsync();
}
}
I am probably going about this bass akwards and WAAAAY wrong but I have been battling with this for hours now trying to figure it out and can't find any examples that look similar.
One thing is that I can return either one just fine if it is in the ActionResult which is strange to me. This below works just fine, but I don't want it in the ActionResult. I would like to have the list retrieval portion in a separate method.
Thanks in advance for any help.
public async Task<ActionResult> PublishList(string query)
{
if (query != "" && query != null)
{
var model = (from n in db.News
where n.newsPublished == false && n.newsTitle.Contains(query)
|| n.newsDescription.Contains(query)
orderby n.newsCreatedDate
select new NewsListViewModel
{
NewsCreatorFName = n.Profile.profileFirstName,
NewsCreatorLName = n.Profile.profileLastName,
NewsID = n.newsID,
NewsCreatorID = n.userID,
NewsTitle = n.newsTitle,
CreatedDate = n.newsCreatedDate
});
return View(await model.ToListAsync());
}
else
{
var model = (from n in db.News
where n.newsPublished == false
orderby n.newsCreatedDate
select new NewsListViewModel
{
NewsCreatorFName = n.Profile.profileFirstName,
NewsCreatorLName = n.Profile.profileLastName,
NewsID = n.newsID,
NewsCreatorID = n.userID,
NewsTitle = n.newsTitle,
CreatedDate = n.newsCreatedDate
});
return View(await model.ToListAsync());
}
}
I have one view that used to display the result of my search item. This is its controller :
[HttpPost]
public ActionResult EvaluatingReport(FormCollection frm)
{
string empType = frm["empType"].ToString();
int totalMonth = 3;
int mon = DateTime.Now.Month;
int yr = DateTime.Now.Year;
string Curdate = mon + "/" + yr;
DateTime date = new DateTime();
var result = (from e in context.tblEmployees
join p in context.tblEmployee_Position on e.PositionIDF equals p.PositionID
select new EvaluateEmployee
{
ID = e.Code,
IDCard = e.IDCard,
Name = e.NameEng,
DOB = e.DOB,
Position = p.Position,
Sex = e.Sex,
StartDate = e.StartDate
}).ToList();
result = result.Where(((s => mon - int.Parse(s.StartDate.Substring(3, 2).ToString()) == totalMonth && yr -int.Parse(s.StartDate.Substring(6, 4).ToString()) == totalYear))).ToList();
ViewData["EmployeeType"] = result;
return View();
}
I displayed the content in the view by looping ViewData["EmployeeType"] and I also included one Print label :
<script language="javascript" type="text/javascript">
function printChart() {
var URL = "EvaluatingReport";
var W = window.open(URL);
W.window.print();
}
function printPage(sURL) {
var oHiddFrame = document.createElement("iframe");
oHiddFrame.src = sURL;
oHiddFrame.style.visibility = "hidden";
oHiddFrame.style.position = "fixed";
oHiddFrame.style.right = "0";
oHiddFrame.style.bottom = "0";
document.body.appendChild(oHiddFrame);
oHiddFrame.contentWindow.onload = oHiddFrame.contentWindow.print;
oHiddFrame.contentWindow.onafterprint = function () {
document.body.removeChild(oHiddFrame); };
}
</script>
<span onclick="printPage('/Report/PrintEvaluatingReport');" style="cursor:pointer;text-decoration:none;color:#0000ff;">
<img src="../../Content/images/Print.png" width="35px;" alt="print" style="position:relative;top:6px;"/>
Print Report
</span>
I used function printPage('/Report/PrintEvaluatingReport') to load the print dialog with the action PrintEvaluatingReport. So I want to take the object that I have in EvaluatingReport to the action PrintEvaluatingReport.
Could anyone tell me how could I do that?
Thanks in advanced.
You could use TempData["EmployeeType"]
[HttpPost]
public ActionResult EvaluatingReport(FormCollection frm)
{
string empType = frm["empType"].ToString();
int totalMonth = 3;
int mon = DateTime.Now.Month;
int yr = DateTime.Now.Year;
string Curdate = mon + "/" + yr;
DateTime date = new DateTime();
var result = (from e in context.tblEmployees
join p in context.tblEmployee_Position on e.PositionIDF equals p.PositionID
select new EvaluateEmployee
{
ID = e.Code,
IDCard = e.IDCard,
Name = e.NameEng,
DOB = e.DOB,
Position = p.Position,
Sex = e.Sex,
StartDate = e.StartDate
}).ToList();
result = result.Where(((s => mon - int.Parse(s.StartDate.Substring(3, 2).ToString()) == totalMonth && yr -int.Parse(s.StartDate.Substring(6, 4).ToString()) == totalYear))).ToList();
ViewData["EmployeeType"] = result;
// Store in TempData to be read by PrintEvaluatingReport
TempData["EmployeeType"] = result;
return View();
}
public ActionResult PrintEvaluatingReport()
{
var employeeType = TempData["EmployeeType"] as EmployeeType;
// do stuff
return View();
}
You can use a session variable for that !!
private EmployeeType Result
{
get { return (EmployeeType)this.Session["Result"]; }
set
{
this.Session["Result"] = value;
}
}
[HttpPost]
public ActionResult EvaluatingReport(FormCollection frm)
{
.
.
.
// Store in Session
this.Result = result;
return View();
}
public ActionResult PrintEvaluatingReport()
{
var employeeType = this.Result;
.
.
.
}