The code below does not compile. The compiler error is
Cannot implicitly convert type 'System.Collections.Generic.List<AnonymousType#1>' to 'System.Collections.Generic.List<AnimeVoter.Models.MyTitleObject>' d:\dev\mvc\AnimeVoter\AnimeVoter\Controllers\SearchController.cs
Below is the code.
[HttpPost]
public ActionResult Search(FormCollection collection)
{
string filter = collection["search_fld"];
List<MyTitleObject> list =
(
from O in db.Titles
join K in db.TitleDescriptions on O.Id equals K.TitleId
where O.Name.ToLower() == filter.ToLower()
select new { Name = O.Name, Description = K.Description, UrlImage = O.UrlImage, Votes = O.Votes }
).ToList(); // this is where the error points at
return View(list);
}
where MyTitleObject is defined as
public class MyTitleObject
{
public string Name { get; set; }
public string Description { get; set; }
public string UrlImage { get; set; }
public int Votes { get; set; }
}
In summary what I am trying to achieve is to send the resulting list to the view.
You just need to specify the type on the select line:
select new MyTitleObject { Name = O.Name, Description = K.Description, UrlImage = O.UrlImage, Votes = O.Votes }
Related
I'm stuck here on a situation wherein I should display the details of a person together with the list of his/her allocations. I've done creating a view model to pass the data to a view but the result is:
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1[EKCMIDTA.ViewModels.EmployeeDetailsVM]', but this dictionary requires a model item of type 'EKCMIDTA.ViewModels.EmployeeDetailsVM'.
For the TicketScannings table, I just wanted to know whether the person has used some of the allocations, and to count how many were used, regardless it it's null.
I hope someone can help me with this.
Thanks!
Controller:
public ActionResult GetDetails(int empId)
{
var employeeInformation = identityContext.AspNetUsers.Find(empId);
var employeeDetails = dbContext.TicketAllocations.Include(a => a.AllocationCategory).Where(t => t.CMId == empId).ToList();
var query = (from alloc in dbContext.TicketAllocations
join scan in dbContext.TicketScannings
on alloc.Id equals scan.TicketAllocationId
join card in dbContext.CardNumberAssignments
on alloc.CMId equals card.CMId into a
from card in a.DefaultIfEmpty()
join reserve in dbContext.ReservedCardNumbers
on card.CardNumberId equals reserve.Id into b
from reserve in b.DefaultIfEmpty()
where (alloc.CMId == empId)
select new EmployeeDetailsVM()
{
Employee = new Employee()
{
FirstName = employeeInformation.FirstName,
LastName = employeeInformation.LastName,
CMId = employeeInformation.Id,
CardNumber = reserve == null ? "No Card Number yet" : reserve.CardNumber,
QRCode = card == null ? "No QR Code yet" : card.QRCode
},
GetTicketAllocations = employeeDetails
});
return View(query);
View Model:
public class EmployeeDetailsVM
{
public Employee Employee { get; set; }
public IEnumerable<Allocation> GetTicketAllocations { get; set; }
}
public class Employee
{
public string CMId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CardNumber { get; set; }
public string QRCode { get; set; }
}
public class Allocation
{
public int AllocationId { get; set; }
public string AllocationName { get; set; }
public int Quantity { get; set; }
public bool IsActive { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
}
View:
#model EKCMIDTA.ViewModels.EmployeeDetailsVM
Looks like your view is only accepting a model of a single EmployeeDetailsVM, but you're passing in a query which would could return multiple.
so you can change #model EKCMIDTA.ViewModels.EmployeeDetailsVM to #model IEnumerable<EKCMIDTA.ViewModels.EmployeeDetailsVM>
or change your GetDetails action to return View(query.FirstOrDefault());
Edit based on comment
public ActionResult GetDetails(int empId)
{
var employeeInformation = identityContext.AspNetUsers.Find(empId);
var employeeTickets = dbContext.TicketAllocations.Include(a => a.AllocationCategory).Where(t => t.CMId == empId).ToList();
var employeeDetails = (from alloc in dbContext.TicketAllocations
join scan in dbContext.TicketScannings
on alloc.Id equals scan.TicketAllocationId
join card in dbContext.CardNumberAssignments
on alloc.CMId equals card.CMId into a
from card in a.DefaultIfEmpty()
join reserve in dbContext.ReservedCardNumbers
on card.CardNumberId equals reserve.Id into b
from reserve in b.DefaultIfEmpty()
where (alloc.CMId == empId)
select new EmployeeDetailsVM()
{
Employee = new Employee()
{
FirstName = employeeInformation.FirstName,
LastName = employeeInformation.LastName,
CMId = employeeInformation.Id,
CardNumber = reserve == null ? "No Card Number yet" : reserve.CardNumber,
QRCode = card == null ? "No QR Code yet" : card.QRCode
}
}).FirstOrDefault();
if (employeeDetails != null)
employeeDetails.GetTicketAllocations = employeeTickets;
return View(employeeDetails);
}
My Model is:
public class HRModel
{
[Required(ErrorMessage = "Please select Year")]
public string SelectedYear { get; set; }
public List<EmployeeSalary> YearList { get; set; }
[Required(ErrorMessage = "Please select Month")]
public int SelectedMonthId { get; set; }
public List<EmployeeSalary> MonthList { get; set; }
public int UserId { get; set; }
public string Username { get; set; }
public string URL { get; set; }
public string Year { get; set; }
public int MonthId { get; set; }
public int Month { get; set; }
}
My Controller is like :
[HttpGet]
public ActionResult Salary()
{
try
{
string UserName = User.Identity.Name.ToString();
ViewBag.UserId = UserName;
HRModel HrModel = new HRModel();
var Year = (from a in dbContext.EmployeeSalaries.Where(f => f.UserName == UserName) select a);
HrModel.YearList = Year.ToList();
return View(HrModel);
}
catch (Exception ex)
{
return RedirectToAction("Index");
}
}
Now in HrModel.YearList I have to pass Year column from the table 'EmployeeSalary', for the use of dropdownlist. The table contains multiple entries with the same Year, due to which dropdownlist is populated with repeating Years.
I'm using following code by selecting a.Year from the table but it's throwing another error:
var Year = (from a in dbContext.EmployeeSalaries.Where(f => f.UserName == UserName) select a.Year).Distinct();
Error in code line:
HrModel.YearList = Year.ToList();
You are selecting the distinct Year property(a string), but you assign the list to a property of type List<EmployeeSalary>, that doesn't work and explains the error.
You could GroupBy this property and just take the first of each group:
HrModel.YearList = dbContext.EmployeeSalaries
.Where(f => f.UserName == UserName)
.GroupBy(f => f.Year)
.Select(g => g.First())
.ToList();
If you don't want to take the first of each group you have to explain the logic.
You have to cast Year to List. For example:
var lstYear = Year.Select(new EmployeeSalary{}).ToList();
ASPNET MVC5 web app
In getting Products, whose relation with other entities is described by following models, I need to filter only those Products.Category.CategoryTrans whose language_id equals the culture param.
Please note I need to pass the result as an IQueryable to subsequent paging and sorting methods, already implemented.
Models:
public partial class Product
{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDeleted { get; set; }
public bool IsApproved { get; set; }
public int CategoryID { get; set; }
public virtual Category Category { get; set; }
[NotMapped]
public virtual CategoryTrans CategoryTrans { get; set; }
}
public partial class Category
{
public int ID { get; set; }
public string Name { get; set; }
public int? ParentID { get; set; }
public bool IsDeleted { get; set; }
public virtual ICollection<Product> Products { get; set; }
public virtual ICollection<CategoryTrans> CategoryTrans { get; set; }
}
public class ISO_Languages
{
public int ID { get; set; }
public string code { get; set; }
public bool IsEnabled { get; set; }
public string name_en { get; set; }
public string name_fr { get; set; }
public string name_it { get; set; }
public string name_de { get; set; }
public string name_es { get; set; }
}
public class CategoryTrans
{
[Key, Column(Order = 1)]
public int category_id { get; set; }
[Key, Column(Order = 2)]
public int language_id { get; set; }
[ForeignKey("category_id")]
public virtual Category categoryId { get; set; }
[ForeignKey("language_id")]
public virtual ISO_Languages languageId { get; set; }
public string name { get; set; }
}
Following query returns ALL CategoryTrans in p.Category.CategoryTrans, that means any category translation
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = (from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select p);
return query;
}
What I am trying to do is filtering, for every product, the single category translation, depending on culture input parameter.
Something like:
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).SingleOrDefault()
};
return query;
}
but getting error:
The entity or complex type 'xyz.DAL.Product' cannot be constructed in a LINQ to Entities query.
Looking for this specific error I now tried projecting onto a DTO:
public class ProductDTO
{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual CategoryTrans CategoryTrans { get; set; }
}
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select new ProductDTO
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).FirstOrDefault()
};
return query.Cast<Product>();
}
And that is now working as expected, returning only required translation to CategoryTrans.
So the query works now BUT casting ProductDTO to needed Product returns:
Unable to cast the type 'xyz.Controllers.ProductDTO' to type 'xyz.Models.Product'. LINQ to Entities only supports casting EDM primitive or enumeration types.
I cannot find a solution to this exception.
Even if you are able to cast ProductDTO to Product model, these objects will not be tracked automatically by EF.
One possible solution may be to first select the Products, then iterate over them to assign the required property.
In your first (failed) query, I believe teh select can be replaced with :
select new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = ct
};
which may work.
Otherwise, you cannot Cast<> from one object type to another unless they have a base/derived relationship. Otherwise, you'll need to convert them:
in Product DTO, add:
replace :
return query.Cast<Product>();
with:
return query.Select(p=> new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.CategoryTrans
};
UPDATE:
Ok, let's try something different. Drop the select from the query, and just use the p object:
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db,
string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture;
return query;
}
that will leave the CategoryTrans property null, but it will get you through this and the other manipulations of the query. When you get to the end, and are actually doing things with the result, then pull out the p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).FirstOrDefault() to get the CategoryTrans
I could not find an answer to the
The entity or complex type 'xyz.DAL.Product' cannot be constructed in a LINQ to Entities query.
error. I eventually solved the problem by adding a
[NotMapped]
public virtual string LocalizedCategoryName { get; set; }
to Product model Class, in charge for displaying localized category name, and moving the filtering to the ViewModel, setting two nested foreach loops, returning a new List of fully localized products:
private List<Product> _LocalizedProductList = new List<Product>();
public List<Product> LocalizedProductList
{
get
{
HttpUtilities HttpHelper = new HttpUtilities();
string culture = HttpHelper.getFullCulture();
int IsoCode = GenericUtilities.getIsoID(culture, db);
List<Product> localized = new List<Product>();
foreach (Product p in _LocalizedProductList)
{
foreach (CategoryTrans c in p.Category.CategoryTrans)
{
if (c.language_id.Equals(IsoCode))
{
Product x = new Product
{
ID = p.ID,
LocalizedCategoryName = c.name,
DateCreated = p.DateCreated,
DateExpire = p.DateExpire,
DateLastModified = p.DateLastModified,
Name = p.Name,
Description = p.Description,
IsApproved = p.IsApproved,
IsDeleted = p.IsDeleted,
ProductImages = p.ProductImages,
User = p.User
};
localized.Add(x);
};
}
}
return localized;
}
set { _LocalizedProductList = value; }
}
No idea if it's the best or the only way to do it, but works as intended. I can now stay with the simple query and pass the returned IQueryable of Product onto the sorting and paging async method or whatever. Whenever I am done, the result is being assigned to ViewModel.LocalizedProductList, where the getter takes care of the final filtering. Thanks to wonderbell for the suggestion that one possible solution could be to first select the Products, then iterate over them to assign the required property. That's why upvoted his/her post even it cannot be considered as a complete (or even partial) solution to the question.
I am trying to get a query that returns everything properly formatted for my ViewModel so I do not have to manually copy everything over from my entity models. I have this Linq query that is giving me an error. :
var query = from i in context.Invoices
join l in context.LineItems on i.InvoiceID equals l.InvoiceID into il
where i.InvoiceID == id
select new InvoiceViewModel()
{
InvoiceID = i.InvoiceID,
CustomerID = i.CustomerID,
InvoiceNote = i.Note,
InvoiceDate = i.InvoiceDate,
Terms = i.Terms,
LineItems = il.ToList<LineItemViewModel>()
};
This is my ViewModel
public class InvoiceViewModel {
public int InvoiceID { get; set; }
public int CustomerID { get; set; }
public string InvoiceNote { get; set; }
public DateTime InvoiceDate { get; set; }
public string Terms { get; set; }
public virtual ICollection<LineItemViewModel> LineItems { get; set; }
}
public class LineItemViewModel {
public int LineItemID { get; set; }
public int InvoiceID { get; set; }
public int Quantity { get; set; }
public string Item { get; set; }
public decimal Amount { get; set; }
public string LineItemNote { get; set; }
}
The error I am getting is (the red squigly is under the il in LineItems = il.ToList())
'IEnumerable<LineItem>' does not contain a definition for 'ToList' and the best extension method overload 'Enumerable.ToList<LineItemViewModel>(IEnumerable<LineItemViewModel>)' requires a receiver of type 'IEnumerable<LineItemViewModel>'
Which I (sorta, kinda, a little) understand. So what is the proper syntax for this?
You need to explicitly initialize your LineItemViewModel instances from the LineItem entities. You might be better off writing this as a correlated subquery rather than a join:
var query =
from i in context.Invoices
where i.InvoiceID == id
select new InvoiceViewModel()
{
InvoiceID = i.InvoiceID,
CustomerID = i.CustomerID,
InvoiceNote = i.Note,
InvoiceDate = i.InvoiceDate,
Terms = i.Terms,
LineItems =
(
from li in context.LineItems
where li.InvoiceID == i.InvoiceID
select new LineItemViewModel
{
LineItemID = li.LineItemID,
InvoiceID = li.InvoiceID,
Quantity = li.Quantity,
Item = li.Item,
Amount = li.Amount,
LineItemNote = li.LineItemNote,
}
).ToList()
};
I would like to get a result set from both PriceAssocationLookup and PriceAssociation tables. How do I do this and not get an error due to Anonymous Type?
Here is my code:
IEnumerable<IPriceAssociationLookupRepository> IPriceAssociationLookupRepository.GetPacs(string upc)
{
using (PortalDataEntities entities = new PortalDataEntities())
{
var priceAssociationLookups = (from priceassociationlookup in entities.PriceAssociationLookups
join priceassociation in entities.PriceAssociations on priceassociationlookup.PriceAssociationCode equals priceassociation.PriceAssociationCode
where priceassociationlookup.Upc == upc
select priceassociationlookup ).ToList();
return priceAssociationLookups;
}
}
Create a ViewModel and add properties for the columns you want to return and return List of the view model type, here is my code, the way i used to do :
List<PreviousTest> Result = (from d in db.dc_tpatient_bookingd
join og in db.dc_tp_organization
on d.clientid equals og.OrgId into a
from og in a.DefaultIfEmpty()
from t in db.dc_tp_test
from p in db.dc_tp_tprocess
where d.bookingid == BookingID
&& t.TestId == d.testid
&& d.ProcessID == p.processid
&& d.bookingdid != BookingDID
select new PreviousTest
{
BookingID = d.bookingid,
BookingDId = d.bookingdid,
TestID = t.TestId,
TestName = t.Test_Name,
ProcessName = p.name,
ProcessID = p.processid,
ClientID = d.clientid
}).ToList();
Here is my viewmodel :
public class PreviousTest
{
public long BookingID { get; set; }
public long BookingDId { get; set; }
public long TestID { get; set; }
public string TestName { get; set; }
public long ProcessID { get; set; }
public string ProcessName { get; set; }
public string ClientID { get; set; }
}