Here is my linq to sql query which is working fine but when i cast and return the data I get casting error.
var productImages = from prod in context.seller_productinventory.AsEnumerable()
join prodImage in context.seller_productimages on prod.prdid equals prodImage.prdid
join category in context.mstr_scategory on prod.mcid equals category.CategoryID
join subcategory in context.mstr_scategory on prod.scid equals subcategory.CategoryID
select new
{
ProductId = prod.prdid,
Category = category.CategoryName,
Subcategory = subcategory.CategoryName,
Image1 = prodImage.image1Path,
Image2 = prodImage.image2Path,
Image3 = prodImage.image3Path,
Image4 = prodImage.image4Path,
ProductStatusCd = (Convert.ToInt32(prod.isAdminApproved) != 1) ? "Pending Approval" : "Approved"
};
I get error in below code.
return (IEnumerable<ProductImageModel>) productImages.ToList();
My Model Class:
public class ProductImageModel
{
public int ProductId { get; set; }
public string Category { get; set; }
public string Subcategory { get; set; }
public string Image1 { get; set; }
public string Image2 { get; set; }
public string Image3 { get; set; }
public string Image4 { get; set; }
public string ProductStatusCd { get; set; }
}
You are selecting an anonymous object using select new and later you are trying to cast a collection of anonymous objects to IEnumerable<ProductImageModel>, that will fail.
You have two options to fix that.
If your class ProductImageModel is not generated through entity framework then you can use that in your select statement like:
select new ProductImageModel
{
//.... fields
}
Or the other option is to create a temporary template class, and project your fields to that class object.
Remember, If ProductImageModel is framework generated then you can't use that in column projection using select.
From your code, it seems that your class ProductImageModel is actually representing a table from database. You will be needing another class (DTO) with fields specified in select clause.
public class ProductImageModelDTO
{
//your fields
}
and then in your LINQ query:
select new ProductImageModelDTO
{
ProductId = prod.prdid,
//rest of the fields.
Your method return type in that case should be:
IEnumerable<ProductImageModelDTO>
When you do select new { ... }, you're creating anonymous objects. Essentially, you end up with IQueryable<object> and that is contravariant with IEnumerable<ProductImageModel> (i.e., the compiler cannot cast from one to the other). The easiest solution is to select actual ProductImageModels if that's what you're going to use:
select new ProductImageModel
{
...
}
Then, no casting is necessary.
Related
I have two tables LookUpCodes and LookUpValues they are defined as below:
public partial class LookUpCodes
{
public int Id { get; set; }
public int? CodeId { get; set; }
public string Code { get; set; }
public string Description { get; set; }
}
public partial class LookUpValues
{
public int Id { get; set; }
public int CodeId { get; set; }
public string CodeValue { get; set; }
public bool? IsActive { get; set; }
}
Each LookUpCode can have multiple Values associated with it. I want to pass in a code and get associated list of values back.
This is probably a common question as I have seen this everywhere, I am not looking for an answer per se, if someone can just explain how to build the proper query I would be obliged.
Here is what I have done so far:
public IEnumerable<LookUpValues> GetValuesByCode(string cd)
{
var query = from code in _context.LookUpCodes
join values in _context.LookUpValues on code.CodeId equals values.CodeId
where code.Code == cd
select new { LookUpValues = values };
return (IEnumerable<LookUpValues>) query.ToList();
}
You are very close to that you are looking for:
public IEnumerable<LookUpValues> GetValuesByCode(string cd)
{
var query = from code in _context.LookUpCodes
join values in _context.LookUpValues
on code.CodeId equals values.CodeId
where code.Code == cd
select values;
return query;
}
Since you have written the join, I assume that you have understood how it works. However let's revisit it:
from a in listA
join b in listB
on a.commonId equals b.commonId
In the above snippet we join the contents of listA with the contents of listB and we base their join on a commonId property existing in items of both lists. Apparently the pair of a and b that fulfill the join criterion it would form one of the possible many results.
Then the where clause is applied on the results of the join. The joined items that pass thewherefilter is the new result. Even at this point the results is still pairs ofaandb`.
Last you project, using the select keyword each pair of the results to a new object. In your case, for each pair of code and values that passed also the where filter, you return only the values.
I have 2 tables in the database :
Table: Order (item_id)
Table: Item ( item_id)
When I'm doing the inner join in entity framework, as you can see below, I need to return in one list the result to manipulate this. Usually when I do the select in one single table , I return a LIST from the entity with the tables name, but I dont know how can I return a LIST when I have 2 or more entity , I mean, using inner join, I would like to return a List that I can manipulate in other class. When I use for only one entity, it is perfect and easy.
public List<????????> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new
{
a.order_numer,
a.total,
b.item_code,
b.item_qty
});
return _result;
}
I don't know how to return it !! I tried to use the .TOLIST(), but still coming "anonymous".
Thank you
First you need to create a custom type like
public class OrderItems
{
public int Order_numer { get; set; }
public int Total { get; set; }
public string Item_code { get; set; }
public int Item_qty { get; set; }
}
After then modify your function like
public List<OrderItems> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new OrderItems()
{
Order_numer= a.order_numer,
Total= a.total,
Item_code=b.item_code,
Item_qty=b.item_qty
}).ToList();
return _result;
}
I hope it will work for you.
You can create a compound model that has a property representing each entity.
public class CompoundModel
{
public Entities.Order { get; set; }
public Entities.Item { get; set; }
}
public List<CompoundModel> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new CompoundModel
{
Order = a
Item = b
});
return _result;
}
Alternatively, if you want to flatten your structure, you can create a class that only has four properties.
public class CompoundModel
{
public string OrderNumber { get; set; }
public int Total { get; set; }
public string ItemCode { get; set; }
public int ItemQuantity { get; set }
}
public List<CompoundModel> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new CompoundModel
{
OrderNumber = a.order_number,
Total = a.total,
ItemCode = b.item_code,
ItemQuantity = b.item_qty
});
return _result;
}
The problem with your code is this part:
select new // This will create an anonymous type
{
a.order_numer,
a.total,
b.item_code,
b.item_qty
}
As the select generates an anonymous type you will get a list of theses anonymous types as a result of the query. In order to get a list typed results, you need to specify the type in the select-clause:
select new TypeYouWantToReturn() // This will create an real type
{
PropA = a.order_numer, // You also need to specify the properties
PropB = a.total, // of the class that you want to assign
PropC = b.item_code, // the resulting values of the query.
PropD = b.item_qty
}
Now the result of the query will return a list of real types. You need to finally call .ToList() so you get a list instead of the IEnumerable that the select statement will return.
join diffrent field type in linq
public partial class Product
{
public int ID { get; set; }
public string CategoryID
{
get { return Myclass.increse(CategoryID); }
set { CategoryID = value; }
}
public string Name { get; set; }
}
public partial class ProductCategory
{
public int ID { get; set; }
public string Name { get; set; }
}
var query = (from c in dContext.ProductCategories
join p in dContext.Products
on Myclass.EncodeMD5(c.ID.ToString()) equals p.CategoryID
select new { id = p.ID, cat = p.CategoryID, name = p.Name, cat1 = c.Name }
).ToList();
The field should be converted to string
Then function runs EncodeMD5
error:
LINQ to Entities does not recognize the method 'System.String
EncodeMD5(System.String)' method, and this method cannot be translated
into a store expression.
You cannot call arbitrary .NET methods in LINQ-to-(some database backend) - the entire point of EF (etc) is that it wants to create SQL from your expression - something involving a where clause. It can work with simple properties and operators, and a few methods it knows about and can map into SQL, but it can't perform something it has never heard of (increse, EncodeMD5, etc) how would it know what SQL to write?
With something like MD5, your best bet would be to store the MD5 hash in the underlying table along with the ID. Likewise with the CategoryID's "increse" (whatever that is). So your query would end up working off these pre-calculated values:
on c.IDHash equals p.CategoryIDHash
I have the following tables:
I'm using Entity Framework Database First, therefore the following entity class is generated:
public partial class Sal1 {
public string SaleID { get; set; }
public string ItemID { get; set; }
public int Quantity { get; set; }
public decimal Total { get; set; }
public virtual Item Item { get; set; }
public virtual Sale Sale { get; set; }
}
Then put the Sal1 rows into a datagrid like this:
private List<Sal1> saleItems = new List<Sal1>();
...
var query = from sa in db.Sal1
where sa.SaleID.Equals(tempSale)
select sa;
foreach(Sal1 si in query) {
saleItems.Add(si);
}
...
dgDetails.ItemsSource = saleItems;
But it turns out like this:
My question is, how should I tweak the query above so that I get the equivalent of the following SQL:
select T0.SaleID, T0.ItemID, T1.Name, T0.Quantity, T0.Total
from Sal1 T0 inner join Item T1 on T0.ItemID = T1.ItemID;
Thanks in advance.
EDIT: I seem to have found a solution, but I had to do this:
var query = from sa in db.Sal1
where sa.SaleID.Equals(tempSale)
select new { sa.SaleID, sa.ItemID, sa.Item.Name,
sa.Item.Manufacturer, sa.Quantity, sa.Total };
And I had to change the type of saleItems to object.
private List<object> saleItems = new List<object>();
Is this the best way to do it?
Just like SQL, LINQ also supports JOINs. You can read more about their syntax here. You should change your query accordingly to get your results. Instead of spoonfeeding the exact answer, I'm guiding you to a more detailed explanation, as it contains valuable information that will help you in the future too.
I'm creating a product listing for an online store. It's pretty standard stuff, a page of product thumbnails with brief details, price and a link through to full details.
I'm using a repository pattern, so I have a central data repository which gives me back tables from a SQL server. I've cut a lot of the code out for the sake of brevity, but just so you get the idea:
public class SqlProductsRepository : IProductsRepository
{
private Table<Product> productsTable;
public SqlProductsRepository(string connectionString)
{
var context = new DataContext(connectionString);
productsTable = context.GetTable<Product>();
// More tables set up here
}
public IQueryable<Product> Products
{
get { return productsTable; }
}
// More properties here
}
I have the following objects mapped to tables:
[Table(Name = "Products")]
public class Product
{
[Column(IsPrimaryKey = true)]
public string ProductCode { get; set; }
[Column]
public string Name { get; set; }
[Column]
public decimal Price { get; set; }
public List<ShopImage> Images = new List<ShopImage>();
}
[Table(Name = "Images_Products")]
public class Image_Product
{
[Column]
public int ImageID { get; set; }
[Column]
public string ProductCode { get; set; }
[Column]
public int DisplayOrder { get; set; }
}
[Table(Name = "Images")]
public class Image
{
[Column(Name = "ImageID")]
public int ImageID { get; set; }
[Column]
public bool Caption { get; set; }
}
If I perform the following query:
// 'db' is the repository (member variable of the controller class)
IQueryable<Product> products = from p in db.Products
join ip in db.Image_Product on p.ProductCode equals ip.ProductCode
where ip.DisplayOrder == 0
select p;
I get a nice IQueryable full of Product objects. However, what I want to do is populate each object's Images list property with a single Image object, with its ID set from the joined Image_Product table.
So I end up with a list of Products, each with one Image in its Images property, which has the ID of the image for that product in the database where DisplayOrder is 0.
I tried this projection, which I thought made sense:
IQueryable<Product> products = from p in db.Products
join ip in db.Image_Product on p.ProductCode equals ip.ProductCode
where ip.DisplayOrder == 0
select new Product {
ProductCode = p.ProductCode,
Price = p.Price,
Images = new List<Image> {
new Image { ImageID = ip.ImageID }
}
};
Which compiles, but throws a runtime error: Explicit construction of entity type 'xxx.Product' in query is not allowed.
Yet elsewhere in the project I do this:
var pages = from i in db.TemplatePageNavigationItems
orderby i.DisplayOrder
select new NavigationItem {
ID = i.PageID,
ParentID = i.ParentID,
Text = i.Name,
Title = i.Name,
Url = (i.Folder == null) ? "" : i.Folder
};
And get no complaints! I assume it's something to do with the first query returning an IQueryable<Product> but I'm not sure why.
Two questions really: why is this not allowed in the first situation, and what should I be doing in order to get my desired result?
As the error says, you can't construct explicit entity types (Product is just that) in your query which should return IQueryable<Product>. Your pages query will return IEnumerable<NavigationItem> and NavigationItem does not seem to be an entity type defined in the database.
You could try returning IEnumerable<Product> in your first query or define a separate type and return IEnumerable of that instead, if you need to project explicit, custom tailored instances of an object.