can't Call Other Service in Select Method- Linq [duplicate] - c#

This question already has answers here:
LINQ to Entities does not recognize the method
(5 answers)
Closed 6 years ago.
I have a query to get all Orders with detail . I have a query like this :
return
_orderMasters.OrderByDescending(row => row.Code).Where(row => row.Code == code).Include(row => row.Orderdetails)
.Select(row => new OrderViewModel
{
Code = row.Code,
// other fields
Items = row.Orderdetails.Select(detail => new OrderItemViewModel
{
ProductcombinationId = detail.ProductCombinationId,
ProductId=detail.ProductAttributeCombination.ProductId,
ProductName = detail.ProductCombination.Product.Name,
ProductCombinationName=_productCombinationService.GetCombinationsName(detail.ProductCombinationId,detail.ProductCombination.ProductId) // * this row
}).ToList(),
ShippingAddress = new AddressViewModel()
{
//set fileds value
}
}).FirstOrDefault();
In line that * I need get ProductcombinationName , to do this I call Method in another Service , but getting this Error :
LINQ to Entities does not recognize the method
First Idea Is , add foreach for All rows and call that Method to get ProductcombinationName , But I don't know is it a good way ?

you can not use c# functions into linq because linq try to execute code on sql side where sql doesn't understand what your c# function is and give error.
for this,
you can do like
Items = row.Orderdetails.Select(detail => new OrderItemViewModel
{
ProductcombinationId = detail.ProductCombinationId,
ProductId=detail.ProductAttributeCombination.ProductId,
ProductName = detail.ProductCombination.Product.Name,
ProductCombination = detail.ProductCombination // need to add for next operation
}).ToList(),
and then
foreach(var item in Items)
{
// add ProductCombinationName code here
}

Entity Framework will not run C# code as part of its query, it has to be able to convert the query to an actual SQL expression.
So we will have to restructure your query expression into an expression that Entity Framework can handle.
var orders = _orderMasters.OrderByDescending(row => row.Code)
.Where(row => row.Code == code)
.Include(row => row.Orderdetails)
.ToList();
return orders.Select(row => new OrderViewModel
{
Code = row.Code,
// other fields
Items = row.Orderdetails.Select(detail => new OrderItemViewModel
{
ProductcombinationId = detail.ProductCombinationId,
ProductId=detail.ProductAttributeCombination.ProductId,
ProductName = detail.ProductCombination.Product.Name,
ProductCombinationName=_productCombinationService.GetCombinationsName(detail.ProductCombinationId,detail.ProductCombination.ProductId) // * this row
}).ToList(),
ShippingAddress = new AddressViewModel()
{
//set fileds value
}
}).FirstOrDefault();

Related

Write query in Entity Framework

I have a query which I ran successfully in SQL Server Management Studio, which returns the table values shown in the screenshot
The query I used is:
SELECT tcoid, COUNT(*) ownleasetank
FROM TankProfile
WHERE ownleasetank = 3
GROUP BY tcoid
Now I'm using Entity Framework to make things easier in my sample project.
I used this method to return the table values as array object:
public async Task<Object> GetLeaseInformationPrincipal()
{
ISOTMSEntities context = new ISOTMSEntities();
var testleaseinfo = from d in context.TankProfiles
join f in context.TankOperators
on d.tcoid equals f.tcoId
where (d.ownleasetank == 3)
select new { f.tcoName, d.ownleasetank } into x
group x by new { x.tcoName } into g
select new
{
tconame = g.Key.tcoName,
ownleasetank = g.Select(x => x.ownleasetank).Count()
};
return testleaseinfo.ToList();
}
but it is not working properly. I also tried other ways, when I use where and groupby method in Entity Framework it doesn't working properly for me.
Does anybody know the solution for this?
It's very simple with LINQ methods:
context.TankProfiles
.Where(t => t.ownleasetank = 3)
.GroupBy(t => t.tcoid)
.Select(g => new {g.Key, g.Count()})
.ToArray();
I have no idea why in your C# version of the query you have such opeartions such join, while your SQL query is very simple. You have to rethink that :)
var c = from t in context.TankProfile
where t.ownleasetank == 3
group t by t.tcoid into g
select new { tcoid=g.Key, ownleasetank=g.Select(x => x.ownleasetank).Count() };
return c.ToList();

Get multiple data from tables Using Entity Framework

public ActionResult Hotel_Read(string text)
{
var result = GetHotel().Where(c => c.Name.Contains(text) || c.City.Contains(text) || c.Country.Contains(text)).ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
private static IEnumerable<HotelViewModel> GetHotel()
{
using (TravelAgancyEntities1 db = new TravelAgancyEntities1())
{
var query = db.Hotels
.Include(p => p.City.Country).Distinct().ToList();
return query.Select(Hotel => new HotelViewModel
{
Name = Hotel.Name,
City = Hotel.City.City_Name,
**Line 10-** Country = Hotel.City.Country.Country_Name,//!!!
});
}
}
When I run the code without line 10, it is working successfully, but when that code is run with line 10, then it's not working.
I assume your code should run properly. the only thing that makes me suspicious, is that you are trying to retrieve all Hotel table data plus 2 other table(with include)
try this :
var q = (from x in db.Hotels.Include(c => c.City).Include(c => c.City.Country)
where x.Id == 5030
select x).Distinct().ToList();
string s = q[0].City.Country.Country_Name;
Limit your select with Where clause.
You don't need Includes here because there is no application logic involved in creation of HotelViewModel instances.
Simple query:
db.Hotels.Select(h => new HotelViewModel
{
Name = h.Name,
City = h.City.City_Name,
Country = h.City.Country.Country_Name,
}).ToList();
Will return from the DB exactly the data that you need.
When you first do Includes, and then call ToList();:
var query = db.Hotels.Include(p => p.City.Select(x => x.Country))
.Distinct()
.ToList();
You fetch form DB all the Hotel properties, all the City properties and
all the Country properties while all you really need is only their names.

Linq: let Count result into a specified column

I've got a table Installation which can contains one or many Equipements.
And for functionnal reasons, I've overwritten my table Installation and added a field NbrEquipements.
I want to fill this field with Linq, but I'm stuck...
Due to special reasons, there is no relation between these to tables. So, no Installation.Equipements member into my class. Therefore, no Installation.Equipements.Count...
I'm trying some stuff. Here is my code:
var query = RepoInstallation.AsQueryable();
// Some filter
query = query.Where(i => i.City.RegionId == pRegionId));
int?[] etatIds = { 2, 3 };
query = (from i in query
select new Installation
{
NbrEquipements= (from e in RepoEquipement.AsQueryable()
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e.SasId
).Count()
});
But with this try, I got this error:
The entity or complex type 'myModel.Installation' cannot be constructed in a LINQ to Entities query
I've tried some other stuff but I'm always turning around...
Another thing that can be useful for me: It would be great to fill a field called Equipements which is a List<Equipement>.
After that, I would be able to Count this list...
Is it possible ?
Tell me if I'm not clear.
Thanks in advance.
Here is the final code:
//In the class:
[Dependency]
public MyEntities MyEntities { get; set; }
//My Methode code:
var query = MyEntities .SasInstallations.AsQueryable();
// Some filter
query = query.Where(i => i.City.RegionId == pRegionId));
var liste = new List<Installation>();
var queryWithListEquipements =
from i in query
select new
{
Ins = i,
EquipementsTemp = (from eq in MyEntities.Equipements.AsQueryable()
where eq.SpecialId == i.SpecialId
&& (etatIds.Contains(eq.SasEquEtat))
select eq
).ToList()
};
var listWithListEquipements = queryWithListEquipements.ToList();
foreach (var anonymousItem in listWithListEquipements)
{
var ins = anonymousItem.Ins;
ins.Equipements = anonymousItem.EquipementsTemp;
ins.NumberEquipements = ins.Equipements.Count();
liste.Add(ins);
}
return liste;
By the way, this is very very fast (even the listing of Equipements). So this is working exactly has I wished. Thanks again for your help everyone!
Use an anonymous type. EF does not like to instantiate entity classes inside a query.
var results = (from i in query
select new
{
NbrEquipements= (from e in RepoEquipement
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e.SasId
).Count()
})
.ToList();
Notice how I used select new instead of select new Installation.
You can then use the data inside the list (which is now in memory) to create instances of type Installation if you want like this:
var installations = results.Select(x =>
new Installation
{
NbrEquipements = x.NbrEquipements
}).ToList();
Here is how to obtain the list of equipment for each installation entity:
var results = (from i in query
select new
{
Installation = i,
Equipment = (from e in RepoEquipement
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e).ToList()
})
.ToList();
This will return a list of anonymous objects. Each object will contain a property called Installation and another property called Equipment (which is a list). You can easily convert this list (of anonymous objects) to another list of whatever type that you want.

How to program sql query with inner join in ASP.Net MVC?

I'm trying to do a LINQ statement using three database tables for my third dropdownlist. Below are my codes but I get an error (for my third dropdownlist) when I choose a cluster in the second dropdownlist.
**//SECTORS**
public JsonResult GetSectors()
{
using (SAMPDBEntities context = new SAMPDBEntities())
{
var ret = context.SECLIBs
.Select(x => new { x.seccd, x.unitacro }).ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
**//CLUSTERS**
public JsonResult GetCluster(string seccd)
{
using (SAMPDBEntities context = new SAMPDBEntities())
{
var ret = context.CLUSLIBs
.Where(x => x.seccd.Contains(seccd))
.Select(x => new { x.cluscd, x.unitdesc }).ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
**//EMPLOYEES**
public JsonResult GetEmployee(string cluscd)
{
using (SAMPDBEntities context = new SAMPDBEntities())
{
var ret = context.UNILIBs
.Where(a => a.cluscd.Contains(cluscd))
.Include(x => x.PPSAs.Select(y => y.EMPFILE.empno))
.ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
Here's my error:
A specified Include path is not valid. The EntityType 'SAMPDBModel.EMPFILE' does not declare a navigation property with the
name 'empno'.
and here's the SQL query (for my third dropdownlist):
SELECT DISTINCT e.empno, e.lname, e.fname, e.mname, c.cluscd
FROM SECLIB a
INNER JOIN CLUSLIB b
ON a.seccd = b.seccd
INNER JOIN UNILIB c
ON b.cluscd = c.cluscd
INNER JOIN PPSA d
ON c.unitcode = d.unitcd
INNER JOIN EMPFILE e
ON d.empno = e.empno
WHERE e.empstat = 1 AND c.cluscd = #cluscd
I need to do a cascading dropdownlist and I need to show the list of employees based on the selected sector and cluster. How can I do that using multiple tables? Please help me. Thanks in advance!
This should be an issue of not specifying the correct respective name that generated from EDMX. Please Can you check the "EMPFILE" Class that generated from Entity Framework It should have similar name with different case sensitive word.
When querying in SQL it does not bother with case sensitivity. But C# is case sensitive language.
And its better if you can post the "EMPFILE" class and database table here.

LINQ to Entities does not recognise custom method

The code below produces the error:
LINQ to Entities does not recognize the method System.String GenerateSubscriptionButton(Int32) method, and this method cannot be translated into a store expression.
How do I create correct custom methods in LINQ to Entities?
var model = _serviceRepository.GetProducts().Select(p => new ProductModel
{
Id = p.Id,
Name = p.Name,
Credits = p.Credits,
Months = p.Months,
Price = p.Price,
PayPalButton = GenerateSubscriptionButton(p.Id)
});
private string GenerateSubscriptionButton(int id)
{
return new PaymentProcessor.PayPalProcessor().CreateSubscriptionButton(id);
}
You can't do that. How should the provider translate your method to SQL?
Remember: LINQ to Entities doesn't actually execute the C# code of your queries. Instead, it interpretes the expressions and translates them to SQL.
In your conrete case, the solution would probably look something like this:
var model = _serviceRepository.GetProducts()
.Select(p => new ProductModel
{
Id = p.Id,
Name = p.Name,
Credits = p.Credits,
Months = p.Months,
Price = p.Price
})
.ToList()
.Select(x =>
{
x.PayPalButton = GenerateSubscriptionButton(x.Id);
return x;
});
The call to ToList executes the query so far against the database and returns the result. From that point forward, the query actually is a LINQ to objects query where the code is not interpreted but executed.
You can't. The problem is, you cannot call GenerateSubscriptionButton from SQL.
You need to retrieve the entities, then once they are in memory, you can call GenerateSubscriptionButton. You can make this happen by adding a call to AsEnumerable before you project your entity onto your model.
var model = _serviceRepository.GetProducts()
.AsEnumerable()
.Select(p => new ProductModel
{
Id = p.Id,
Name = p.Name,
Credits = p.Credits,
Months = p.Months,
Price = p.Price,
PayPalButton = GenerateSubscriptionButton(p.Id)
});

Categories

Resources