I want to, in the midst of a linq to sql query where clause, check against a public int. I am getting this error: Method 'Int32 isInDept(System.String)' has no supported translation to SQL.
Vaguely related classes (from a public static class called ad):
//get AD property
public static string GetProperty(this Principal principal, String property) {
DirectoryEntry directoryEntry = principal.GetUnderlyingObject() as DirectoryEntry;
if (directoryEntry.Properties.Contains(property))
return directoryEntry.Properties[property].Value.ToString();
else
return String.Empty;
}
public static string GetDepartment(this Principal principal) {
return principal.GetProperty("department");
}
The Classes in question (from a different class):
public int isInDept(string department) {
PrincipalContext domain = new PrincipalContext(ContextType.Domain);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(domain, GetUserId());
if (department == userPrincipal.GetDepartment()) {
return 3;
}
else { return 2; }
}
public intranetGS.viewArticle viewArticle(int id) {
string user = GetUserId();
var result = ( from a in n.articles
join s in n.sections on a.section equals s.section_id
join p in n.privacies on a.privacy equals p.privacy_id
let iid = isInDept(s.name)
where (a.active == true && a.article_id == id && a.privacy < iid) ||
(a.active == true && a.article_id == id && a.privacy == 3 && a.author == user)
select new intranetGS.viewArticle {
articleId = a.article_id,
title = a.title,
author = a.author,
html = a.html,
section = s.name,
privacy = p.name,
dateCreated = a.date_created,
dateModified = a.date_modified,
userCreated = a.user_created,
userModified = a.user_modified
}).First();
var nv = (from v in n.navs
join s in n.sections on v.section equals s.section_id
let iid = isInDept(s.name)
where (v.active == true && s.name == result.section && v.privacy < 3) ||
(v.active == true && s.name == result.section && v.privacy == iid && v.user_created == user)
select v.html);
StringBuilder sb = new StringBuilder();
foreach (var r in nv) {
sb.Append(nv);
}
result.articleNav = sb.ToString();
return result;
}
What am I doing wrong? If I can't do it this way, how is it suggested that it be done?
It is not possible to translate that function to SQL, one workaround for this is to make most of your query with linq to sql, and use Linq to Objects for the rest. It should be something like this:
var query = ( from a in n.articles
join s in n.sections on a.section equals s.section_id
join p in n.privacies on a.privacy equals p.privacy_id
where (a.active == true && a.article_id == id)
select new intranetGS.viewArticle {
articleId = a.article_id,
title = a.title,
author = a.author,
html = a.html,
section = s.name,
privacy = p.name,
privacyId = a.privacy,
dateCreated = a.date_created,
dateModified = a.date_modified,
userCreated = a.user_created,
userModified = a.user_modified
}).ToList();
And then filter the list:
var result = query.Where(a => (a.privacyId < isInDept(a.section)) ||
(a.privacyId == 3 && a.author == user)).First();
Then you can do the same for the second query.
Related
I have three tables TableTeam, TableUser and TableLink. I want to join them to get a list.
var teams = _db.TableTeam;
var users = _db.TableUser;
var managerIds = teams.Select(x=>x.ManagerId).ToList();
var list = (from user in _db.TableUser
where user.EndDate == null && user.ManagerId != null && managerIds.Contains(user.ManagerId.Value)
let r = _db.TableLink.FirstOrDefault(l => l.ProjectId == projectId && l.UserId == user.UserId)
let t = _db.TableTeam.FirstOrDefault(m => m.ManagerId == user.ManagerId)
select new MyDto
{
ProjectId = projectId,
UserId = user.UserId,
IsAssigned = r.AssignedId > 0 ?true : false,
AssignedId = r.AssignedId,
Percent = r.Percent.HasValue ? (r.Percent.Value).ToString() + "%": ""
}).GroupBy(d => d.UserId).ToList();
For the table TableLink, the corresponding dataSet class in entity framework is:
public LinkDto
{
public int AssignedId {get;set;}
public short ProjectId {get;set;}
public short UserId {get;set;}
public decimal? Percent {get;set;}
// ...
}
However I got the error:
Nullable object must have a value
I think that it may be caused by decimal? Percent. But not sure how to fix it. Also I can use the store d procedure as well, which means if you can solve it by SQL query, that is also great.
It turns out I have to move let codes before where clause then add the condition to where.
Such as
var list = (from user in _db.TableUser
let r = _db.TableLink.FirstOrDefault(l => l.ProjectId == projectId && l.UserId == user.UserId)
let t = _db.TableTeam.FirstOrDefault(m => m.ManagerId == user.ManagerId)
where user.EndDate == null && user.ManagerId != null && managerIds.Contains(user.ManagerId.Value)
&& r != null && t != null
select new MyDto
{
ProjectId = projectId,
UserId = user.UserId,
IsAssigned = r.AssignedId > 0 ?true : false,
AssignedId = r.AssignedId,
Percent = r.Percent.HasValue ? (r.Percent.Value).ToString() + "%": ""
}).GroupBy(d => d.UserId).ToList();
//I tried to implement global search using the below query
//my linq query :
var query = (from ug in db.SC_UserGroup
where ug.IsDeleted == false && ug.TenantID == tenantId && ug.ParentGroup == defaultGuid && ug.GroupTypeID == manualCodeTypeId
select new
{
GroupID = ug.ID,
GroupTypeID = ug.GroupTypeID,
GroupName = ug.GroupName,
Description = ug.Description,
TenantId = ug.TenantID,
SubGroups = (from sug in db.SC_UserGroup
where sug.ParentGroup == ug.ID && sug.IsDeleted == false && sug.TenantID == tenantId
select new
{
GroupID = sug.ID,
GroupTypeID = sug.GroupTypeID,
GroupName = sug.GroupName,
Description = sug.Description,
TenantId = sug.TenantID,
users = (from sugm in db.SC_UserGroupMap
join su in db.SC_User on sugm.UserID equals su.ID
join usertenantmap in db.SC_UserTenantMap on su.ID equals usertenantmap.UserID
join userCredential in db.SC_UserCredential on usertenantmap.UserCredentialID equals userCredential.ID
where su.IsDeleted.Value == false && sugm.UserGroupID == sug.ID && sugm.IsDeleted == false
select new
{
UserId = su.ID,
UserName = (su.FirstName + " " + su.LastName),
EmailId = userCredential.Email
}).Distinct().ToList()
})
});
// here my search array contails the list of words to search
if (searchArray[0] != string.Empty)
{
//like this i am able to search on GroupName and Description column
query = query.Where(x => searchArray.All(y => x.GroupName.Contains(y) || x.Description.Contains(y)));
}
MY question :
I want to search on fields of sub- query fields (i.e on SubGroups fields in the current context)
If you want to do the same search on fields in SubGroups you'll have to use All or Any depending on if you want all the items in SubGroups to match or at least one.
query = query.Where(
x => searchArray.All(
y => x.GroupName.Contains(y) ||
x.Description.Contains(y) ||
x.SubGroups.Any(sg => sg.GroupName.Contains(y) ||
x.SubGroups.Any(sg => sg.Description.Contains(y))));
I'm using VS2010 Entity Framework to store a value in a session. I the use syntax below:
private IEnumerable _TransactionItem2
{
get
{
var msg = HttpContext.Current.Session["SESSION_MESSAGES_NAME"] as IEnumerable;
if (msg == null)
{
msg = new BOMDetailController().GetSearchData(0, 0);
HttpContext.Current.Session["SESSION_MESSAGES_NAME"] = msg;
}
return msg;
}
set
{
Session[_MenuName + "TransactionItem"] = value;
}
}
Session initialization method below:
public IEnumerable GetSearchData(int companyID = 0, long bOMID = 0)
{
var itemBrand = (from p in this.controllerCMN.Context.CmnItemBrands where p.IsDeleted == false select p).AsEnumerable();
var itemColor = (from p in this.controllerCMN.Context.CmnItemColors where p.IsDeleted == false select p).AsEnumerable();
var itemMaster = (from p in this.controllerCMN.Context.CmnItemMasters where p.IsDeleted == false select p).AsEnumerable();
var itemSpecificationMaster = (from p in this.controllerCMN.Context.CmnItemSpecificationMasters where p.IsDeleted == false select p).AsEnumerable();
var itemStyleMaster = (from p in this.controllerCMN.Context.CmnItemStyleMasters where p.IsDeleted == false select p).AsEnumerable();
var uOM = (from p in this.controllerCMN.Context.CmnUOMs where p.IsDeleted == false select p).AsEnumerable();
var bnOMMaster = (from p in this.Context.PlnBOMMasters where p.IsDeleted == false && p.CompanyID == companyID select p).AsEnumerable();
var prdPhase = (from p in this.Context.PlnPrdPhases where p.IsDeleted == false && p.ComapnyID == companyID select p).AsEnumerable();
var prdTask = (from p in this.Context.PlnPrdTasks where p.IsDeleted == false && p.ComapnyID == companyID select p).AsEnumerable();
var bOMDetail = (from p in this.Context.PlnBOMDetails where p.IsDeleted == false && p.CompanyID == companyID select p).AsEnumerable();
var query = from p in bOMDetail
select new
{
BOMDetailRecordID = p.BOMDetailRecordID,
CustomCode = p.CustomCode,
BOMID = p.BOMID,
BOMName = (from q in bnOMMaster where q.BOMID == p.BOMID select q.Description).FirstOrDefault(),
PhaseID = p.PhaseID,
PhaseName = (from q in prdPhase where q.PhaseID == p.PhaseID select q.PhaseName).FirstOrDefault(),
ItemID = p.ItemID,
ItemName = (from q in itemMaster where q.ItemID == p.ItemID select q.ItemName).FirstOrDefault(),
ColorID = p.ColorID,
ColorName = (from q in itemColor where q.ColorID == p.ColorID select q.ColorName).FirstOrDefault(),
StyleID = p.StyleID,
StyleName = (from q in itemStyleMaster where q.StyleID == p.StyleID select q.StyleName).FirstOrDefault(),
ItemSpecificationID = p.ItemSpecificationID,
ItemSpecificationName = (from q in itemSpecificationMaster where q.ItemSpecificationID == p.ItemSpecificationID select q.Description).FirstOrDefault(),
ItemBrandID = p.ItemBrandID,
BrandName = (from q in itemBrand where q.ItemBrandID == p.ItemBrandID select q.ItemBrandName).FirstOrDefault(),
UOMID = p.UOMID,
UOMName = (from q in uOM where q.UOMID == p.UOMID select q.UOMName).FirstOrDefault(),
ItemQty = p.ItemQty,
UnitPrice = p.UnitPrice,
StatusID = p.StatusID,
};
return query.WhereIf(bOMID != 0, p => p.BOMID == bOMID).OrderByDescending(w => w.BOMDetailRecordID);
}
I want to query on the above property TransactionItem2.
1) I want to count how many items on the property TransactionItem2
`TransactionItem2.AsQueryable().Count()`
2) I want to query on this like:
var entity = _ TransactionItem2.SingleOrDefault(item => item.BOMDetailRecordID == childRecordID);
3) I want to use a query
var entity = _ TransactionItem2.Where(item => item.BOMDetailRecordID == childRecordID);
My Extension method is
public static TSource Single<TSource>(this IEnumerable source)
{
return source.Cast<TSource>().Single();
}
public static TSource Single<TSource>(this IEnumerable source, Func<TSource, bool> predicate)
{
return source.Cast<TSource>().Single(predicate);
}
public static TSource SingleOrDefault<TSource>(this IEnumerable source)
{
return source.Cast<TSource>().SingleOrDefault();
}
public static TSource SingleOrDefault<TSource>(this IEnumerable source, Func<TSource, bool> predicate)
{
return source.Cast<TSource>().SingleOrDefault(predicate);
}
Working syntax:
var entity = _TransactionItem2.SingleOrDefault(item => item.BOMDetailRecordID == childRecordID);
The above syntax shows an error message:
“cannot be inferred from the usage. Try specifying the type arguments
explicitly”
The above syntax is not working for the property TransactionItem2. Why is 1,2,3 not working?
You have to specify TSource explicitly when calling your methods:
var entity = _TransactionItem2.SingleOrDefault<EntityClass>(item => item.BOMDetailRecordID == childRecordID);
I have the following method:
public DataTable.DataTablesPage<DataTable.UserModel> DataTableUserListByAttendees(int geoArea, int CurrentUserID)
{
var result = from i in _dbContext.Users
where i.GeographicalAreas.Any(p => p.GeoAreaID == geoArea)
select new DataTable.UserModel()
{
ID = i.ID,
Company = i.Company,
DCMember = (i.UserId != null),
FirstName = i.FirstName,
LastName = i.LastName
};
}
it works fine, but it returns entities that dont have the geoArea proeprty set.
public DataTable.DataTablesPage<DataTable.UserModel> DataTableUserListByAttendees(int? geoArea, int CurrentUserID)
{
var result = from i in _dbContext.Users
where i.GeographicalAreas.Any(p => p.GeoAreaID == geoArea)
select new DataTable.UserModel()
{
ID = i.ID,
Company = i.Company,
DCMember = (i.UserId != null),
FirstName = i.FirstName,
LastName = i.LastName
};
}
How can I change the query so that it returns only entities that have their geoArea property set (aka is not null).
where (geoArea == null) || i.GeographicalAreas.Any(p => p.GeoAreaID == geoArea)
or conditionally add the where to the query
That should be
where geoArea == null || i.GeographicalAreas.Any(p => p.GeoAreaID == (int)geoArea)
On our online billing application, we give a billing summary of what bills the customer received and the payments they made.
In order for this to work, I have to first pull the payments then match them to the bills. So I have do something like:
foreach (BillPaymentSummary payment in billPayments)
{
DateTime dt = payment.DueDate;
// Debug errors on this next line
var summary = (from a in db.BillHistories
where a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL"
select new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
}).SingleOrDefault();
if (summary != null)
{
summary.PayDate = payment.PaidDate;
summary.AmountPaid = payment.AmountPaid;
returnSummaries.Add(summary);
}
else
{
summary = (from a in db.BillHistories
where a.CustomerId == customerNumber && a.DueDate == payment.DueDate && a.Type == "ADJ "
select new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
}).SingleOrDefault();
if (summary != null)
{
summary.PayDate = payment.PaidDate;
summary.AmountPaid = payment.AmountPaid;
returnSummaries.Add(summary);
}
}
}
I have been playing with this, but no matter what I do, I get the following error message:
The entity or complex type 'UtilityBill.Domain.Concrete.BillSummary' cannot be constructed in a LINQ to Entities query.
Is it because I am running queries within queries? How can I get around this error?
I have tried searching Google for an answer and see many answers, but none of them seem to explain my problem.
You cannot project onto a mapped entity. You would have to call ToList() before doing your mapping.
Or better yet, change to the following (calling FirstOrDefault will execute the query and allow you to populate your object):
var summary = db.BillHistories.FirstOrDefault(a => a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL").Select(x => new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
});
To decouple yourself from the Entity Framework you may want to also consider using a different model class to return instead of the Entity Framework model.
What I ended up doing was:
foreach (BillPaymentSummary payment in billPayments)
{
var data = db.BillHistories.Where(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "B").FirstOrDefault();
if (data != null) // There is a bill history
{
returnSummaries.Add(new BillSummary
{
Id = data.Id,
CustomerId = data.CustomerId,
DueDate = data.DueDate,
PreviousBalance = data.PreviousBalance,
TotalBill = data.TotalBill,
Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")),
IsFinalBill = data.IsFinalBill,
PayDate = payment.PaidDate,
AmountPaid = payment.AmountPaid
});
}
else // No bill history record, look for an adjustment
{
data = db.BillHistories.FirstOrDefault(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "A");
if (data != null)
{
returnSummaries.Add(new BillSummary
{
Id = data.Id,
CustomerId = data.CustomerId,
DueDate = data.DueDate,
PreviousBalance = data.PreviousBalance,
TotalBill = data.TotalBill,
Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")),
IsFinalBill = data.IsFinalBill,
PayDate = payment.PaidDate,
AmountPaid = payment.AmountPaid
});
}
}
db.SaveChanges();
}