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)
});
Related
I am trying to get the same results as with a SQL query using Entity Framework method syntax.
SQL query :
select
mr.*, mrf.userId as RequesterUserId, mrt.UserId as ReceiverUserId
from
MoneyRequests mr
inner join
MoneyReqFrom mrf on mr.MoneyRequestId = mrf.MoneyRequestId
inner join
MoneyReqTo mrt on mr.MoneyRequestId = mrt.MoneyRequestId
where
mr.MoneyRequestId = 'acfc8008-4cf7-47ec-a3fe-0fe245af77cc'
EF Linq method syntax :
var moneyreqResponse = context.MoneyRequests
.Join(context.MoneyReqFroms,
mr => mr.MoneyRequestId,
mrf => mrf.MoneyRequestId,
(mr, mrf) => new
{
MoneyRequestId = mr.MoneyRequestId,
Amount = mr.Amount,
RequestType = mr.RequestType,
CreationDate = mr.CreationDate,
RequesterUserId = mrf.UserId
})
.Join(context.MoneyReqTos,
mr => mr.MoneyRequestId,
mrt => mrt.MoneyRequestId,
(mr, mrt) => new
{
MoneyRequestId = mr.MoneyRequestId,
Amount = mr.Amount,
RequestType = mr.RequestType,
CreationDate = mr.CreationDate,
ReceiverUserId = mrt.UserId,
Email = mrt.Email
})
.Where(fullEntry => fullEntry.MoneyRequestId == "acfc8008-4cf7-47ec-a3fe-0fe245af77cc")
.ToList();
I retrieve the data from the database except the column RequesterUserId.
Do you know why?
Thanks
Your query returns a MoneyRequests type, which I belive does not contain RequesterUserId.
You should define a new type with all the properties you need (those returned by the join) and add it to your DbContext.
Also probably you want to mark your new type as keyless
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.
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();
I have the following EF Expression:
var complexes = db.ResidentialComplexes.AsNoTracking()
.Where(rc => rc.MasterEntity == entity)
.Select(rc => new CustomComplexObj()
{
ComplexId = rc.ComplexId,
Name = rc.Name,
Region = rc.Region,
Properties = rc.CurrentProperties.Select(p=> new CustomPropertyObj(){
Name = p.Name,
PropertyId = p.PropertyId
}).ToList()
}).ToList();
Im getting an error when setting:
Properties = rc.CurrentProperties.Select(p=> new CustomPropertyObj(){
Name = p.Name,
PropertyId = p.PropertyId
}).ToList()
This is the error:
LINQ to Entities does not recognize the method 'System.Collections.Generic.List1[CondoTrack.Model.Poco.CustomPropertyObj] ToList[CustomPropertyObj](System.Collections.Generic.IEnumerable1[CondoTrack.Model.Poco.CustomPropertyObj])' method, and this method cannot be translated into a store expression.
Any clue on how to get the desired result?
Remove the ToList() and change the Properties type to IEnumerable<T> instead of List<T>. As it is stated in the error, ToList is not supported by Linq to Entities.
I have the following LINQ query:
var allocations =
from ta in dc.TransactionAllocations
where ta.Allocated == false
group ta by new { ta.ReceiptReference, ta.Customer } into tag
select new
{
Customer = tag.Key.Customer,
ReceiptReference = tag.Key.ReceiptReference,
Invoices = tag.ToDictionary(a => new AllocationDictionaryKey()
{
ID = a.ID,
InvoiceReference = a.InvoiceReference
},
a => a.Amount)
}
But when I try to execute this, the ToDictionary call fails as it's not a supported LINQ-to-SQL operator. The only way around this I have seen is to call ToDictionary at the end of the query, but I only want one property of my anonymous type to be a dictionary!
Any ideas on how to go about doing this?
Have a look at using AsEnumerable. This is designed to get round operators that are not supported by a specific platform. It means that the data will be processed where the code is rather than where the data is though.
Invoices = tag.AsEnumerable().ToDictionary(a => new AllocationDictionaryKey() { ID = a.ID, InvoiceReference = a.InvoiceReference }, a => a.Amount)
Quite old, but here goes.
I solved my problem with
from ta in dc.TransactionAllocations.AsEnumerable()
i.e. directly making the datatable as Enumerable.