How do you format a datetime field in a SelectList in MVC? - model-view-controller

I'm creating a new SelectList object and concatenating 2 fields, one is a string and the other is a DateTime. Basically I'm building a dropdownlist displaying the name and date of an event. When I try running the code I get the error ' LINQ to Entities does not recognize the method 'System.String ToShortDateString()' method, and this method cannot be translated into a store expression.'
Any help would greatly be appreciated.
ViewBag.EventKey = new SelectList((from e in db.Events where e.Active == true select new { e.PKey, EventInfo = e.Name + " " + e.EventDate.ToShortDateString() }), "Pkey", "EventInfo");

The problem is that you're calling .ToShortDateString in statement that is going to be translated to DB query. Try following:
ViewBag.EventKey = new SelectList((from e in db.Events where e.Active == true select e).ToArray().Select(e => new { e.PKey, EventInfo = e.Name + " " + e.EventDate.ToShortDateString() }), "Pkey", "EventInfo");

Related

LINQ to Entities does not recognize the method 'Boolean HasFlag(System.Enum)' method, and this method cannot be translated into a store expression

I have this service:
//seroiunoiweucroewr
///wercewrwerwerwer
//wcererewrwerwer
public List<UserRoleContract> GetRolePagesByUserId(long plngUserId, DisplayType displayType)
{
List<UserRoleContract> result = new List<UserRoleContract>();
using (CitiCallEntities context = new CitiCallEntities())
{
try
{
//var DisplayList = Utility.GetEnumDescriptions(typeof(DisplayType)).ToList();
//var selectValue = DisplayList.Where(i => i.Key == (byte) DisplayType.Windows).FirstOrDefault();
result = (from oUser in context.User
join oUserRole in context.UserRole on oUser.Id equals oUserRole.UserId
join oRoleRightsPage in context.RoleRightsPage.Where(i => i.IsActive == true)
on oUserRole.RoleId equals oRoleRightsPage.RoleId
join oApplicationPage in context.ApplicationPage.Where(i => i.IsActive == true)
on oRoleRightsPage.PageId equals oApplicationPage.Id
join oRole in context.Role on oUserRole.RoleId equals oRole.Id
join oEmployee in context.Employee on oUser.EmployeeId equals oEmployee.Id
join oSection in context.Section on oEmployee.SectionId equals oSection.Id
where oUser.IsActive == true && oUser.Id == plngUserId
&& oRole.IsActive == true && (((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType))
//am getting error in has flag
// am having three display type web, windows and all
// how to overcome
select new UserRoleContract
{
UserId = oUser.Id,
RoleId = oRole.Id,
RoleName = oRole.RoleName,
PageID = oApplicationPage.Id,
PageName = oApplicationPage.PageName,
IsOPsCtrl = oRole.IsOPsCtrl,
ISOPsCtrlFor = oRole.OPsCtrlFor,
SectionId = oSection.Id,
DisplayType = oRoleRightsPage.DisplayType,
}).Distinct().ToList();
}
catch (Exception exception)
{
HandleExpcetion(exception);
//throw new CitiCallException(exception.Message);
}
}
return result;
}
I am getting Linq error in has flag conversion, how do I overcome this problem?
you are geeting error because HasFlag method is not paresent in database i.e. it might be part of language or local function in code which is not present in database.
So when query is translated it found this method is not available and that is the reason you are getting error.
one solution to avoid this error is
Brind all data from databae
Than filter than data, i.e. apply HasFlag method of it.
But this will bring all data and might decrease performance.
Example is
remove this line (((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType) from your query
var list = querieddata //first fetch data without hasflag condition/method
.AsEnumerable() // Rest of the query in-process
.Where(oRoleRightsPage=> ((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType))//apply condition here once fetching done
.ToList();
The HasFlag method has no equivalent in Linq to Entities which is why you get that error. You can get around it by using bitwise comparison instead of using HasFlag, for example this:
((DisplayType)oRoleRightsPage.DisplayType).HasFlag(displayType)
Becomes:
(oRoleRightsPage.DisplayType & displayType) > 0

Automapper with linq how?

Ok, I'm really struggling with finding a good example of what I need to do. So, I'll ask here.
Let's say I have a entity class (EF) named Customer and a corresponding view-model class named CustomerViewModel.
Using AutoMapper, I have created the following mappings:
Mapper.CreateMap<CustomerViewModel, Customer>();
Mapper.CreateMap<Customer, CustomerViewModel>();
How would I modify the following code to make use of this mapping?
public static List<CustomerViewModel> GetCustomers()
{
using (var context = new GCSBaseEntities())
{
var query = from c in context.Customers
select new CustomerViewModel
{
CompanyName = c.CompanyName,
Id = c.Id,
EmailAddress = c.EmailAddress,
FirstName = c.FirstName,
LastName = c.LastName,
MiddleName = c.MiddleName,
ModifiedDate = c.ModifiedDate,
Phone = c.Phone,
SalesPerson = c.SalesPerson,
Suffix = c.Suffix,
Title = c.Title,
FullName = c.FirstName + " " + c.LastName
};
return query.ToList();
}
}
Thanks in advance.
When you register your mappings, you must provide any complex mapping operations that have to occur. In your case, I believe all your properties match up, except for FullName = c.FirstName + " " + c.LastName. Here's how your Customer-to-CustomerViewModel mapping should look:
Mapper.CreateMap<Customer, CustomerViewModel>()
.ForMember(custVm => custVm.FullName,
mapper => mapper.MapFrom(cust => cust.FirstName + " " + cust.LastName));
You'll have to figure out how to shove the FullName prop from the ViewModel back into the FirstName & LastName fields on the EF class, though. But when you decide how to implement it, follow the pattern from above for the other mapping.
Your query can now be MUUUCH smaller:
using (var context = new GCSBaseEntities())
{
return from c in context.Customers
select Mapper.Map<CustomerViewModel>(c);
}
Figured it out. In order to avoid the aforementioned error, you have to Add the call the .AsEnumerable() after Customers like so:
return from c in context.Customers.AsEnumerable()
select Mapper.Map<CustomerViewModel>(c);
I got this from this thread: LINQ and AutoMapper

if-else clause in Linq to entity framework query

Following Linq to Entities query is causing the "Unable to create a constant value of type 'Data.InhouseUnit'. Only primitive types ('such as Int32, String, and Guid') are supported in this context" exception.
IList<FaultReport> faultReports = (from fr in _session.FaultReports
where fr.CreatedOn > dateTime
select new FaultReport
{
Id = fr.Id,
ExecutionDate = fr.ExecutionDate ?? DateTime.MinValue,
FaultType = fr.FaultType,
Quarters = fr.Quarters,
InhouseSpaceId = fr.InhouseSpaceId,
InhouseSpace = new InhouseSpace { Id = fr.InhouseSpace.Id, Name = fr.InhouseSpace.Name },
InhouseUnitId = fr.InhouseUnitId ?? Guid.Empty,
**InhouseUnit = fr.InhouseUnitId == Guid.Empty ? null : new InhouseUnit { Id = fr.InhouseUnit.Id, Name = fr.InhouseUnit.Name }**
}).ToList();
Specifically, it is the if expression in bold font which causes the exception. I need to make the check as fr.InhouseUnitId is a nullable. If I take out the the bolded expression, the rest of the statement works just fine. I have spent a fair amount of time, in msdn forum and on web, to understand what is causing the exception but still cannot quite understand. Guid is scalar so it should work, right? Even this expression InhouseUnit = true ? null: new InhouseUnit() in place of the bolded expression in the above statement wouldn't work. Can we even write if/else
If i try to write an extension method to take away the logic and just return a result, following exception is thrown:
LINQ to Entities does not recognize the method 'System.Object
GuidConversion(System.Nullable`1[System.Guid], System.Object)' method, and this method
cannot be translated into a store expression
It looks like you are projecting into new objects of the same type that you are querying from. Is that the case? It seems a little weird, but assuming you have a good reason for doing this, you could split the query into two parts. The first part would get what you need from the database. The second part would run locally (i.e. LINQ-to-Objects) to give you the projection you need. Something like this:
var query =
from fr in _session.FaultReports
where fr.CreatedOn > dateTime
select new {
fr.Id,
fr.ExecutionDate,
fr.FaultType,
fr.Quarters,
InhouseSpaceId = fr.InhouseSpace.Id,
InhouseSpaceName = fr.InhouseSpace.Name,
InhouseUnitId = fr.InhouseUnit.Id,
InhouseUnitName = fr.InhouseUnit.Name,
};
IList<FaultReport> faultReports = (
from fr in query.ToList()
select new FaultReport {
Id = fr.Id,
ExecutionDate = fr.ExecutionDate ?? DateTime.MinValue,
FaultType = fr.FaultType,
Quarters = fr.Quarters,
InhouseSpaceId = fr.InhouseSpaceId,
InhouseSpace = new InhouseSpace { Id = fr.InhouseSpaceId, Name = fr.InhouseSpaceName },
InhouseUnitId = fr.InhouseUnitId ?? Guid.Empty,
InhouseUnit = fr.InhouseUnitId == Guid.Empty ? null : new InhouseUnit { Id = fr.InhouseUnitId, Name = fr.InhouseUnitName }
}).ToList();

Entity Framework - LINQ selection in POCO generic List property

I'm having some issues setting a generic list property of a POCO object when from an EF context. For instance I have a very simple object that contains the following:
public class foo
{
public string fullName;
public Entity entity;
public List<SalesEvent> eventList;
}
My code to populate this object from looks something like this:
.Select(x => new foo()
{
fullName = x.vchFirstName + " " + x.vchLastName,
entity = new EntityVo()
{
address1 = x.vchAddress1,
entityId = x.iEntityId,
emailAddress = x.vchEmailAddress,
firstName = x.vchFirstName,
lastName = x.vchLastName,
city = x.vchCity,
state = x.chState,
workNumber = x.vchWorkNumber,
mobileNumber = x.vchMobileNumber,
siteId = x.iSiteId
}
eventList = _context.Events
.Where(e => e.iEntityId == x.iEntityId
&& e.iStatusId >= eventStatusMin
&& e.iStatusId <= eventStatusMax)
.Select(e => new List<SalesEventMatchVo>
{
new SalesEventMatchVo()
{
vehicleName = _context.Quotes.Select(q=>q).Where(q=>q.iEventId == e.iEventId).FirstOrDefault().vchMake + " " + _context.Quotes.Select(q=>q).Where(q=>q.iEventId == e.iEventId).FirstOrDefault().vchModel,
eventId = e.iEventId,
salesPerson = e.chAssignedTo,
eventStatusDesc=_context.RefDefinitions.Select(r=>r).Where(r=>r.iParameterId==e.iStatusId).FirstOrDefault().vchParameterDesc,
eventStatusId =(int)e.iStatusId,
eventSourceDesc=_context.RefDefinitions.Select(r=>r).Where(r=>r.iParameterId==e.iSourceId).FirstOrDefault().vchParameterDesc,
createDate = e.dtInsertDate
}
}).FirstOrDefault()
}).ToArray();
This issue I'm having is that I'm unable to populate the eventList property with all of the events, it's only grabbing the first record(which makes sense looking at the code). I just cant seem to figure out to populate a the entire list.
Is there a reason simply removing the FirstOrDefault at the end isn't the solution here? I feel like I might be misunderstanding something.
EDIT:
I think I see what you are trying to do. The issue is that you are creating a list in the select statement, when the select statement works only over one thing at a time. It is basically mapping an input type to a new output type.
Try something like this instead:
eventList = _context.Events.Where(e => e.iEntityId == x.iEntityId && //FILTER EVENTS
e.iStatusId >= eventStatusMin &&
e.iStatusId <= eventStatusMax)
.Select(e => new SalesEventMatchVo() //MAP TO SALESEVENT
{
vehicleName = _context.Quotes.Select(q=>q).Where(q=>q.iEventId == e.iEventId).FirstOrDefault().vchMake + " " + _context.Quotes.Select(q=>q).Where(q=>q.iEventId == e.iEventId).FirstOrDefault().vchModel,
eventId = e.iEventId,
salesPerson = e.chAssignedTo,
eventStatusDesc=_context.RefDefinitions.Select(r=>r).Where(r=>r.iParameterId==e.iStatusId).FirstOrDefault().vchParameterDesc,
eventStatusId =(int)e.iStatusId,
eventSourceDesc=_context.RefDefinitions.Select(r=>r).Where(r=>r.iParameterId==e.iSourceId).FirstOrDefault().vchParameterDesc,
createDate = e.dtInsertDate
})
.ToList() //CONVERT TO LIST
As a side note, unless you actually need a List for some reason, I would store foo.eventList as IEnumerable<SalesEvent> instead. This allows you to skip the List conversion at the end, and in some scenarios enables neat tricks like delayed and/or partial execution.
Also, I'm not sure what the point of your .Select(q=>q) statements are in several lines of the SalesEventMatchVo initializer, but I'm pretty sure you can chop them out. If nothing else, you should Select after Where, as Where can reduce the work performed by all following statements.

Using LINQ to pull MembershipUser.Username into a new object

I have the following code and I need to pull out each user's username from the membership tables:
var results = (from u in db.U_USER
where u.Forename.ToLower().Contains(search)
|| u.Surname.ToLower().Contains(search)
select new ExUser
{
MembershipId = u.MembershipId,
Surname = u.Surname,
Forename = u.Forename,
Username = Membership.GetUser(u.MembershipId).UserName
});
Now I know why im getting the following, but can anybody recommend a solution?
LINQ to Entities does not recognize the method 'System.Web.Security.MembershipUser GetUser
LINQ to Entities is trying to translate your select expression into T-SQL, which it can't because there's no ExUser etc. in T-SQL.
Finhish off the expression with a call to AsEnumerable or similar, and then perform the projection:
var results = (from u in db.U_USER
where u.Forename.ToLower().Contains(search)
|| u.Surname.ToLower().Contains(search)
select u)
.AsEnumerable()
.Select(u => new ExUser
{
MembershipId = u.MembershipId,
Surname = u.Surname,
Forename = u.Forename,
Username = Membership.GetUser(u.MembershipId).UserName
});
You can do it by forcing the results into memory by using AsEnumerable. When the results are in memory you can call Membership.GetUser without linq attempting to translate it to sql:
var results = (from u in db.U_USER
where u.Forename.ToLower().Contains(search) || u.Surname.ToLower().Contains(search)
).AsEnumerable().Select(u => new ExUser {
MembershipId = u.MembershipId,
Surname = u.Surname,
Forename = u.Forename,
Username = Membership.GetUser(u.MembershipId).UserName
});

Resources