using ToString() in linq expression to convert DateTime value - c#

I'm trying to convert a DateTime value to a string, but I'm getting this runtime error:
Additional information: LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be
translated into a store expression.
This is the query I'm using:
using (var db = new DbContext())
{
var results = (from u in db.AspNetUserses
join upi in db.UserPersonalInfoes on u.Id equals upi.UserId into upis
from upi in upis.DefaultIfEmpty()
join up in db.UserPreferenceses on u.Id equals up.UserId into ups
from up in ups.DefaultIfEmpty()
join us in db.UserStatses on u.Id equals us.UserId into uss
from us in uss.DefaultIfEmpty()
select new
{
Username = u.UserName,
Telephone = (upi == null ? String.Empty : upi.Telephone),
ID = u.Id,
LastLogin = (us == null ? String.Empty : us.LastLoginDate)
}).ToList();
gvUsers.DataSource = results;
gvUsers.DataBind();
}
Any idea how can I fix this error?

Create a second list and do the transformation there.
using (var db = new DbContext())
{
var results = (from u in db.AspNetUserses
join upi in db.UserPersonalInfoes on u.Id equals upi.UserId into upis
from upi in upis.DefaultIfEmpty()
join up in db.UserPreferenceses on u.Id equals up.UserId into ups
from up in ups.DefaultIfEmpty()
join us in db.UserStatses on u.Id equals us.UserId into uss
from us in uss.DefaultIfEmpty()
select new
{
Username = u.UserName,
Telephone = (upi == null ? String.Empty : upi.Telephone),
ID = u.Id,
LastLogin = (us == null ? DateTime.MinValue : us.LastLoginDate)
}).ToList();
var list = (from r in results
select new {
Username = r.UserName,
Telephone = r.Telephone,
ID = r.ID
LastLogin = r.LastLogin == DateTime.MinValue ? "" : r.LastLogin.ToString()
}).ToList();
gvUsers.DataSource = list;
gvUsers.DataBind();
}

Related

MongoDB Linq query in C# with filters

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;
}

The type of one of the expressions in the join clause is incorrect in Entity Framework. Constant in left join

I'm trying to do a left join in an EF query. I'm getting the following error:
Error CS1941 The type of one of the expressions in the join clause is
incorrect. Type inference failed in the call to 'GroupJoin'
and here is the C# code:
var foo = from m in db.ClientMasters
join a in db.Orders on new { m.Id, Status = "N" } equals new { a.ClientID, a.Status } into a_join
from a in a_join.DefaultIfEmpty()
select new { m.ClientID, a.ID };
The column names have to match in the join; here is the corrected code:
var foo = from m in db.ClientMasters
join a in db.Orders on new { ClientID = m.Id, Status = "N" } equals new { a.ClientID, a.Status } into a_join
from a in a_join.DefaultIfEmpty()
select new { ClientID = m.Id, OrderId = a.Id };

MVC- Specified cast is not valid

New to MVC, Checked lot of workarounds.. didn't help:
This code is written in model repository, which returns a list that I can return to View(Index)
IList<AccessArticles> publisherList = (from aa in db.AccessArticles
join u in db.Users on aa.UserId equals u.id
join a in db.Articles on aa.ArticleId equals a.id
where u.id == id
orderby a.title
select new
{
UserName = u.username,
ArticleTitle = a.title,
AccessArticlesId = aa.AccessArticlesId,
ArticleId = aa.ArticleId,
UserId = aa.UserId
})
.AsEnumerable()
.Select
(x=> new AccessArticles
{
AccessArticlesId = x.AccessArticlesId,
UserId = x.UserId,
UserName = x.UserName,
ArticleTitle = x.ArticleTitle
}).ToList();
Error that I get is Specified cast is not valid.
Please suggest a wayout or a better way to get the same effect.
Thanks
Code reference -
Interface :
List<AccessArticles> SearchByUserId(int UserId);
Repository :
public List<AccessArticles> SearchByUserId(int id)
{
var setArticles = (from aa in db.AccessArticles
join u in db.Users on aa.UserId equals u.id
join a in db.Articles on aa.ArticleId equals a.id
where u.id == id
orderby a.title
select new AccessArticles
{
UserName= u.username,
ArticleTitle = a.title,
AccessArticlesId= aa.AccessArticlesId,
ArticleId = aa.ArticleId,
UserId = aa.UserId
}).ToList();
return setArticles;
}
Controller
public ActionResult Index(int? id)
{
int UserId = 0;
if (id != null)
{
UserId = Convert.ToInt32(id);
}
IAccessArticlesRepository AccessRepository = new AccessArticlesRepository();
//int count = AccessRepository.SearchByUserId(UserId).Count();
List_AccessArticles = AccessRepository.SearchByUserId(UserId);
return View(List_AccessArticles);
}
Model
namespace theSiteCMS.Models
{
public partial class AccessArticles
{
public string ArticleTitle { get; set; }
public string UserName { get; set; }
}
}
I did some changes taking some reference:
----------
Repository
----------
public IQueryable<AccessArticles> SearchByUserId(int id)
{
var setArticles = (from aa in db.AccessArticles
join u in db.Users on aa.UserId equals u.id
join a in db.Articles on aa.ArticleId equals a.id
where u.id == id
orderby a.title
select new AccessArticles
{
UserName= u.username,
ArticleTitle = a.title,
AccessArticlesId= aa.AccessArticlesId,
ArticleId = aa.ArticleId,
UserId = aa.UserId
});
return setArticles;
}
--------------
Controller
--------------
public ActionResult Index(int? id)
{
int UserId = 0;
if (id != null)
{
UserId = Convert.ToInt32(id);
}
IAccessArticlesRepository AccessRepository = new AccessArticlesRepository();
var userwisearticles = AccessRepository.SearchByUserId(UserId);
return View(userwisearticles);
}
Error:
In Index.aspx page:
<% foreach (var item in Model) { %>
Highlight on 'Model' - Explicit construction of entity type 'theSiteCMS.Models.AccessArticles' in query is not allowed.
This returns a collection of Anonymous types with the properties described below. If you need to use an existing class, make sure it's not the one your EF is using to represent your entity unless it matches directly. If that's the case, then you should be able to to replace the select new below with select aa and have it return a list of the entity models that EF built for you.
var publisherList = (from aa in db.AccessArticles
join u in db.Users on aa.UserId equals u.Id
join a in db.Articles on aa.ArticleId equals a.Id
where u.Id == userId
orderby a.Title
select new
{
UserName = u.UserName,
ArticleTitle = a.Title,
AccessArticleId = aa.AccessArticlesId,
UserId = aa.UserId
}).ToList();
Edited to select the EF entity directly;
var publisherList = (from aa in db.AccessArticles
join u in db.Users on aa.UserId equals u.Id
join a in db.Articles on aa.ArticleId equals a.Id
where u.Id == userId
orderby a.Title
select aa).ToList();
That should trigger a compile error because your return type doesn't match. I'm guessing it has to be List<AccessArticle>

LINQ query with List<> and asking if is null

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();

Linq to SQL with Group by

I am trying to convert this T-SQL to a Linq To SQL but can't work out the group by aggregate functions. Any help welcome.
select c.ClientID, GivenName, Surname, max(a.Address), max(t.Value)
from Client c
left join ClientAddress a on c.ClientID = a.ClientID
left join ClientContact t on c.ClientID = t.ClientID
group by c.ClientID, GivenName, Surname
To group by a composite key, you typically use an anonymous type:
var qry = from x in someSource
group x by new { x.ClientID, x.GivenName, x.Surname } into grp
select new { grp.Key, Address = grp.Max(x => x.Address),
Value = grp.Max(x => x.Value) };
The exact answer I came up with was
public IQueryable<ClientSearchDTO> GetClientsDTO()
{
return (from client in this.Context.Clients
join address in this.Context.ClientAddresses on client.ClientID equals address.ClientID
join contact in this.Context.ClientContacts on client.ClientID equals contact.ClientID
where contact.ContactType == "Phone"
group client by new { client.ClientID, client.Surname, client.GivenName } into clientGroup
select new ClientSearchDTO()
{
ClientID = clientGroup.Key.ClientID,
Surname = clientGroup.Key.Surname,
GivenName = clientGroup.Key.GivenName,
Address = clientGroup.Max(x => x.ClientAddresses.FirstOrDefault().Address),
PhoneNumber = clientGroup.Max(x => x.ClientContacts.FirstOrDefault().Value)
});
}

Categories