I am not sure what I am doing wrong. But the linq to sql is choking when I do a toList.
it is running this area of the select.
case RightSearchType.Text:
If put the results in a var variable and not use the ToList it runs fine gets the results no problem.
I have tried
ToList()
ToList<URRightsView>()
Both of them yield the same issue.
I wish to pass back a strongly type List when developers call this method.
Please keep in mind this is not finished code. This is the first time I am using LINQ to SQL and my very first test to see if I am doing it right.
Thus failing badly.
Any help in resolving the casting problem is truly appreciated :)
public static List<URRightsView> Search(string SearchText, long Id, RightSearchType SearchType)
{
List<URRightsView> dRights = null;
try
{
using (DataContext db = new DataContext(AppSettings.Settings.ConnectionString))
{
Table<URRights> tRights = db.GetTable<URRights>();
Table<URRoles> tRoles = db.GetTable<URRoles>();
Table<URApps> tApps = db.GetTable<URApps>();
Table<URRightRoleMapping> tMapRoles = db.GetTable<URRightRoleMapping>();
Table<URApplicationRight> tMapApps = db.GetTable<URApplicationRight>();
string results = string.Empty;
switch (SearchType) {
case RightSearchType.Application:
dRights = (from ma in tMapApps
join apps in tApps on ma.AppFK equals apps.AppId
join r in tRights on ma.RightFK equals r.RightId
where (r.Title.Contains(SearchText) || r.Description.Contains(SearchText)) && ma.AppFK == Id
orderby r.Title, apps.Name ascending
select new URRightsView
{
Title = r.Title,
Classification = r.Classification,
Description = r.Description,
RightId = URUtil.GetLong(r.RightId),
RightType = r.RightType,
AppName = apps.Name
}).ToList<URRightsView>();
break;
case RightSearchType.Role:
dRights = (from ma in tMapApps
join apps in tApps on ma.AppFK equals apps.AppId
join r in tRights on ma.RightFK equals r.RightId
join mr in tMapRoles on r.RightId equals mr.RightFK
where (r.Title.Contains(SearchText) || r.Description.Contains(SearchText)) && ma.AppFK == Id
orderby r.Title, apps.Name ascending
select new URRightsView
{
Title = r.Title,
Classification = r.Classification,
Description = r.Description,
RightId = URUtil.GetLong(r.RightId),
RightType = r.RightType,
AppName = apps.Name
}).ToList<URRightsView>();
break;
case RightSearchType.Text:
dRights = (from ma in tMapApps
join apps in tApps on ma.AppFK equals apps.AppId
join r in tRights on ma.RightFK equals r.RightId
where r.Title.Contains(SearchText) || r.Description.Contains(SearchText)
orderby r.Title, apps.Name ascending
select new URRightsView
{
Title = URUtil.GetString(r.Title),
Classification = URUtil.GetString(r.Classification),
Description = URUtil.GetString(r.Description),
RightId = URUtil.GetLong(r.RightId),
RightType = URUtil.GetLong(r.RightType),
AppName = URUtil.GetString(apps.Name)
}).ToList<URRightsView>();
break;
}
}
}
catch (Exception ex)
{
URErrors.HandleError(ex, UserName);
JavaScriptSerializer serial = new JavaScriptSerializer();
string error = "URRights.Search Method: Could not Search Text - " + SearchText + ", SearchType = " + SearchType.ToString() + ",Id = " + Id.ToString() + Environment.NewLine;
URErrors.HandleError(ex, UserName);
throw new Exception(error);
}
return dRights;
}
UPDATE WITH EXCEPTION
Message
Specified cast is not valid.
at System.Data.SqlClient.SqlBuffer.get_Int64()
at System.Data.SqlClient.SqlDataReader.GetInt64(Int32 i)
at Read_URRightsView(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at URCore.URSecurity.URRights.Search(String SearchText, Int64 Id, RightSearchType SearchType) in D:\Development\Websites\unravelingspirit\URCore\URSecuirty\URRights.cs:line 244
Related
So I have the list that I want to join against a table on the db.
I am getting the error Unable to create a constant value of type, what am I doing wrong?
List<info.user> studyAccessList = new List<info.User>();
using (var Db = new Entities())
{
//get users from USER table
var UserDbQry = (from data in Db.USER
where data.System == "something" & data.Active == true
select data);
//outer join
var joinQry =
from s1 in UserDbQry
join t2 in studyAccessList
on new
{
Study = s1.Study,
Email = s1.Email
}
equals new
{
Study = t2.Study,
Email = t2.Email
}
into rs
from r in rs.DefaultIfEmpty()
//where r == null
select s1;
foreach (var inactiveUser in joinQry)
{
//add tag for system.
//create xml
string xml = String.Format("<User><Study>{0}</Study><Email>{1}</Email><Active>false</Active></User>", inactiveUser.Study, inactiveUser.Email);
recordCount = recordCount + ProcessXml(wsu, xml, log.ErrorMsgPrefix);
}
}
I needed to change the first query to a list then the second query was able to pick it up.
//get users from USER table
var UserDbQry = (from data in Db.USER
where data.System == "something" & data.Active == true
select data).ToList;
//outer join
var joinQry =
from s1 in UserDbQry
join t2 in studyAccessList
on new
{
Study = s1.Study,
Email = s1.Email
}
equals new
{
Study = t2.Study,
Email = t2.Email
}
into rs
from r in rs.DefaultIfEmpty()
//where r == null
select s1;
I am trying to do a LINQ query on several Mongo collections. All the collections have to be joined based on ApplicationId and an outer Join has to be done - so that persons that have no statuses are returned as well.
The JOIN part and everything around it works as expected. The problem is that when I add a filter to one of the collections, the whole thing breaks
An exception of type 'System.ArgumentException' occurred in System.Linq.Expressions.dll but was not handled in user code: 'Expression of type 'System.Collections.Generic.IEnumerable`1[CDM.Person]' cannot be used for parameter of type 'System.Linq.IQueryable`1[CDM.Person]' of method 'System.Linq.IQueryable`1[CDM.Person] Where[Person](System.Linq.IQueryable`1[CDM.Person], System.Linq.Expressions.Expression`1[System.Func`2[CDM.Person,System.Boolean]])''
Here is my query
var applications = _dbContext.GetCollection<Application>(typeof(Application).Name).AsQueryable().Where(
x => x.OrganizationID == TokenContext.OrganizationID);
var persons = _dbContext.GetCollection<Person>(typeof(Person).Name).AsQueryable().Where(p =>p.FirstName == "j");
var statuses = _dbContext.GetCollection<ApplicationStatus>(typeof(ApplicationStatus).Name).AsQueryable();
var mortgages = _dbContext.GetCollection<Mortgage>(typeof(Mortgage).Name).AsQueryable();
var statusQuery = from a in applications
join p in persons on a.ApplicationID equals p.ApplicationID
join s in statuses on a.ApplicationID equals s.ApplicationID into pas
join m in mortgages on a.ApplicationID equals m.ApplicationID into morgs
from subWHatever in pas.DefaultIfEmpty()
select new ApplicationStatusProjection
{
ApplicationId = a.ApplicationID,
FirstName = p.FirstName,
LastName = p.Surname,
Prefix = p.Prefix,
DateOfBirth = p.DateOfBirth,
Initials = p.Initials,
PostalCode = p.Addresses.First().PostalCode,
MortgageAmount = morgs.Sum(i => i.MortgageTotal) ?? 0,
StatusExpireAt = subWHatever.ExpireAt ?? DateTime.MinValue,
StatusMessageText = subWHatever.MessageText ?? "",
StatusMessage = subWHatever.MessageStatus ?? ""
};
if (!String.IsNullOrEmpty(orderBy))
{
statusQuery = statusQuery?.OrderBy(orderBy);
}
if (nrOfRecords != null)
{
statusQuery = statusQuery?.Take(nrOfRecords.Value);
}
// Execute the query
var result = statusQuery?.ToList();
return result;
I followed the guidelines here https://mongodb.github.io/mongo-csharp-driver/2.6/reference/driver/crud/linq/ and I also tried this
var statusQuery =
from a in applications
join p in persons on a.ApplicationID equals p.ApplicationID into pa
from paObject in pa.DefaultIfEmpty()
join s in statuses on paObject.ApplicationID equals s.ApplicationID into pas
But I got the same error as before.
Thank you in advance.
So after may tryouts I have discovered that you cannot filter before the join because of the way the LINQ query is translated to Mongo query.
The fix for this is to have the filtering afterwards, on the statusQuery object. In that case, the filtering has to happen on the projected object (so a new filter is needed).
See below how I solved it:
//get collections
var applications = _dbContext.GetCollection<Application>(typeof(Application).Name).AsQueryable().Where(
x => x.OrganizationID == TokenContext.OrganizationID);
var persons = _dbContext.GetCollection<Person>(typeof(Person).Name).AsQueryable();
var statuses = _dbContext.GetCollection<ApplicationStatus>(typeof(ApplicationStatus).Name).AsQueryable();
var mortgages = _dbContext.GetCollection<Mortgage>(typeof(Mortgage).Name).AsQueryable();
//query
var query = from a in applications
join p in persons on a.ApplicationID equals p.ApplicationID
join s in statuses on a.ApplicationID equals s.ApplicationID into applicationStatusView
join m in mortgages on a.ApplicationID equals m.ApplicationID into morgs
from subStatus in applicationStatusView.DefaultIfEmpty()
select new ApplicationStatusProjection
{
ApplicationId = a.ApplicationID,
FirstName = p.FirstName,
LastName = p.Surname,
Prefix = p.Prefix,
DateOfBirth = p.DateOfBirth,
Initials = p.Initials,
Addresses = p.Addresses ?? new List<Address>(),
PostalCode = p.Addresses.First().PostalCode,
MortgageAmount = morgs.Sum(i => i.MortgageTotal) ?? 0,
StatusExpireAt = subStatus.ExpireAt ?? DateTime.MinValue,
StatusMessageText = subStatus.MessageText ?? "",
StatusMessage = subStatus.MessageStatus ?? "",
StatusDate = subStatus.StatusDate
};
//filter & order
var filteredResult = ApplyFilters(query, searchCriteria);
if (!String.IsNullOrEmpty(orderBy))
{
filteredResult = filteredResult?.OrderBy(orderBy);
}
if (nrOfRecords != null)
{
filteredResult = filteredResult?.Take(nrOfRecords.Value);
}
// Execute the query
var result = filteredResult?.ToList();
return result;
And applying the filters (there is probably a smarter way to do this):
private IQueryable<ApplicationStatusProjection> ApplyFilters(IQueryable<ApplicationStatusProjection> query, ApplicationStatusProjectionSearch searchCriteria)
{
if (!string.IsNullOrEmpty(searchCriteria.FirstName))
{
query = query.Where(x => x.FirstName.ToLower().StartsWith(searchCriteria.FirstName));
}
if (!string.IsNullOrEmpty(searchCriteria.LastName))
{
query = query.Where(x => x.LastName.ToLower().StartsWith(searchCriteria.LastName));
}
if (!string.IsNullOrEmpty(searchCriteria.PostalCode))
{
query = query.Where(x => x.Addresses.Any(a => a.PostalCode.ToLower().StartsWith(searchCriteria.PostalCode)));
}
//other irrelevant filters
return query;
}
I've had issues with my query that I was finally able to work through, but now duplicate date is formed even with Distinct(). I know these joins are messy, unfortunately it's what I have to do since the tables I'm working with have no relationships between them.
try
{
//work on query further , need to get client ID correctly
if (vehicleses.Count == 0)
return null;
string siteId = QueryExportSiteWithId(exportSiteId).SiteId;
// db.Database.Log = Console.Write;
var joinedInventorySettings = await (from id in db.Inventory_Descriptions
join iv in db.Inventory_Vehicles
on new {client = id.ClientID, id = id.InventoryID} equals new {client = iv.ClientID, id = iv.ID}
into descGroup
from m in descGroup.DefaultIfEmpty()
join se in db.Settings_Exports
on m.ClientID equals se.ClientID into settingGroup
from sg in settingGroup.DefaultIfEmpty()
join sl in db.Settings_Lots
on new {client = m.ClientID, id = m.LotID} equals new {client = sl.ClientID, id = sl.ID} into
lotsGroup
from lg in lotsGroup.DefaultIfEmpty()
join ses in db.Settings_ExportSites on new {client = m.ClientID, lotId = m.LotID, site = siteId}
equals new {client = ses.ClientID, lotId = ses.LotID, site = ses.Site} into exportGroup
from eg in exportGroup.DefaultIfEmpty()
join ifs in db.Inventory_Features
on new {client = m.ClientID, id = m.ID} equals new {client = ifs.ClientID, id = ifs.InventoryID}
into invFeatGroup
from ifg in invFeatGroup.DefaultIfEmpty()
join ip in db.Inventory_Photos
on m.ID equals ip.InventoryID into photo
from photos in photo.DefaultIfEmpty()
where m.Archived != "1"
&& m.Holding != "1"
&& m.Status == "A"
&& clientIdList.Contains(m.ClientID)
select new JoinedInventorySettings()
{
InventoryVehicles = m,
InventoryDescriptions = id,
SettingsExports = sg,
//InventoryPhotos = ,
SettingsLots = lg,
InventoryFeatures = ifg,
SettingsExportSites = eg
}).Distinct().ToListAsync();
if (joinedInventorySettings != null)
{
returnList.AddRange(joinedInventorySettings);
return returnList;
}
return null;
}
If anyone is curious, I was able to fix the issue by grouping items by two of the entity keys that I know will be in the dataset.
I have some method with linq query. Logic is next, if I pass null for list of role ids, I want all roles to be included in process, but if it has value, I want only those with id in the list. I am receiving exeption.
public static List<NameEmail> GetNameEmailPairs(Guid guid, List<int> recipientRoles)
{
using (var tc = TransactionContext())
{
var dc = tc.DataContext;
var nameEmailPairs = (
from email in dc.Emails
join logon in dc.Logons on email.GUID equals logon.GUID
join eLogon in dc.ELogons on logon.UID equals eLogon.LogonGUID
join role in dc.Roles on entityLogon.PrimaryPermissionRoleID equals role.RoleID
where
(recipientRoles == null || recipientRoles.Contains(role.RoleID))
select new NameEmail
{
Email = email.EmailAddress,
FullName = GetName(logon.GUID)
}
)
.ToList();
return nameEmailPairs;
}
}
This part is breaking (recipientRoles == null || recipientRoles.Contains(role.RoleID)). Can you please help me with this, what should I do?
To make debugging easier, break your query up into pieces like this:
var nameEmailPairs = (
from email in dc.Emails
join logon in dc.Logons on email.GUID equals logon.GUID
join eLogon in dc.ELogons on logon.UID equals eLogon.LogonGUID
join role in dc.Roles on entityLogon.PrimaryPermissionRoleID equals role.RoleID
select new {email, role}
);
if(recipientRoles != null)
{
nameEmailPairs = nameEmailPairse.Where(
recipientRoles.Contains(p => p.role.RoleID)
);
}
var nameEmailPairs = (from p in nameEmailPairs
select new NameEmail
{
Email = email.EmailAddress,
FullName = GetName(logon.GUID)
}).ToList();
This is a follow up from here -->multiple-sorting-on-linq-nested-method .
Basically, on let memberName = ... it is throwing this exception Method 'System.String MemberName(Int32)' has no supported translation to SQL. and I am not figuring out the solution.
Also, BLLCmo and BLLConnect actually use TWO different DataBases. The original app(not mine) uses 4 Seperate DB's so I am trying to make due.
BLLCmo.cs
public static DataTable GetAllMembers(Guid workerID)
{
var AllEnrollees = from enrollment in context.tblCMOEnrollments
where enrollment.CMOSocialWorkerID == workerID || enrollment.CMONurseID == workerID
join supportWorker in context.tblSupportWorkers on enrollment.EconomicSupportWorkerID equals supportWorker.SupportWorkerID into workerGroup
from worker in workerGroup.DefaultIfEmpty()
let memberName = BLLConnect.MemberName(enrollment.ClientID)
orderby enrollment.DisenrollmentDate ascending, memberName ascending
select new
{
enrollment.ClientID,
MemberName = memberName,
NurseName = BLLAspnetdb.NurseName(enrollment.CMONurseID),
SocialWorkerName =BLLAspnetdb.SocialWorkerName(enrollment.CMOSocialWorkerID),
enrollment.DisenrollmentDate,
enrollment.EnrollmentDate,
ESFirstName = worker.FirstName,
ESLastName = worker.LastName,
ESPhone = worker.Phone
};
var dataTable = AllEnrollees.CopyLinqToDataTable();
return dataTable;
}
BLLConnect.cs
public static String MemberName(Int32 personID)
{
var memberName = from person in context.tblPersons
where person.PersonID == personID
select person.FirstName + " " + person.LastName;
return memberName.SingleOrDefault();
}
The problem is that LINQ to SQL is trying to translate your method into SQL. Since MemberName isn't valid SQL, it gives up. Instead, you'll need to pull down the data you need from SQL and then call your methods (and sort) in a separate LINQ to Objects query:
public static DataTable GetAllMembers(Guid workerID)
{
var AllEnrollees =
from enrollment in context.tblCMOEnrollments
where enrollment.CMOSocialWorkerID == workerID || enrollment.CMONurseID == workerID
join supportWorker in context.tblSupportWorkers on enrollment.EconomicSupportWorkerID equals supportWorker.SupportWorkerID into workerGroup
from worker in workerGroup.DefaultIfEmpty()
select new
{
enrollment.ClientID,
enrollment.CMONurseID,
enrollment.CMOSocialWorkerID,
enrollment.DisenrollmentDate,
enrollment.EnrollmentDate,
ESFirstName = worker.FirstName,
ESLastName = worker.LastName,
ESPhone = worker.Phone
};
var result =
from enrollee in AllEnrollees.AsEnumerable()
let memberName = BLLConnect.MemberName(enrollee.ClientID)
orderby enrollee.DisenrollmentDate ascending, memberName ascending
select new
{
enrollee.ClientID,
MemberName = memberName,
NurseName = BLLAspnetdb.NurseName(enrollee.CMONurseID),
SocialWorkerName = BLLAspnetdb.SocialWorkerName(enrollee.CMOSocialWorkerID),
enrollee.DisenrollmentDate,
enrollee.EnrollmentDate,
enrollee.ESFirstName,
enrollee.ESLastName,
enrollee.ESPhone
};
return result.CopyLinqToDataTable();
}