EF Select inside Select - c#

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.

Related

C# Entity Framework join tables

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

Adding Match operators dynamically in a Group Aggregate on MongoDB

I'm using MongoDB C# driver 2.4.4 in my web application. I need to group documents in a collection filtering them dynamically.
var query = collection.Aggregate()
.Match(y => y.IdLower.Contains(id))
.Match(y => y.NameLower.Contains(name))
.Group(
key => key.Id,
g => new
{
Id = g.Key
}).ToList();
I need to add or remove Match operators based to user input but I cannot figure how.
I tried something like this:
var query = collection.Aggregate();
if(!string.IsNullOrWhiteSpace(id))
query = query.Match(y => y.IdLower.Contains(id));
if (!string.IsNullOrWhiteSpace(name))
query = query.Match(y => y.NameLower.Contains(name));
query = query.Group(
key => key.Id,
g => new
{
Id = g.Key
}).ToList();
but I get syntax error Cannot imlicitly convert type System.Collection.Generic.List<<anonymous type: string Id>> to '...
How to achieve something like this?
The problem is that the type of query is IAggregateFluent<T1> (where T1 is your document type), but the return type of the .Group() method is IAggregateFluent<T2> (where T2 is an anonymous type). The compiler does not know how to implicitly convert these types, hence the error.
It depends on what you're trying to do here, but one possible way to fix this would be to return instances of T1 (your document type) from the group expression:
query = query.Group(
key => key.Id,
g => new T1 // replace "T1" with the actual name of your class
{
Id = g.Key
}).ToList();
Another option would be to assign the results of the group function to a new variable:
var grouped = query.Group(
key => key.Id,
g => new
{
Id = g.Key
}).ToList();
Hope this helps.

LINQ throws error on using Regex.Split()

ERROR
LINQ to Entities does not recognize the method 'System.String[] Split(System.String, System.String)' method, and this method cannot be translated into a store expression.
FOR CODE
var getfrmbid = (from e in _dbEntity.FormNames
where e.form_id == id & e.type == "Form"
select new FormsCreationModel
{
form_name = e.form_name,
form_id = e.form_id,
formfields = (from i in _dbEntity.FormDetails
where e.form_id == i.form_id
select i).AsEnumerable().Select(x=> new FormDetailsModel()
{
field_default = x.field_default,
field_id = x.field_id,
field_mandatory = x.field_mandatory,
field_maxlength = x.field_maxlength,
field_name = x.field_name,
field_type = x.field_type,
field_validation = x.field_validation,
field_value = Regex.Split(x.field_value, " ^ ").Select(item => new DropDownValue() { DDValue = item }).ToList()
}).ToList()
}).Single();
NOTE
Error Spot at field_value is of type List<DropDownValue> in FormDetailsModel
x.field_value is a String and I am converting it into an String[] using Regex.Split() and then to List<DropDownValue> to assign it on field_value.
How could I assign field_value from x.field_value after splitting?
You must replace
select i).AsEnumerable().Select(x=> new FormDetailsModel()
with
select i).ToList().Select(x=> new FormDetailsModel()
When you use .ToList(), DB is queried and Select extension runs locally. Otherwise lambda expression is compiled into sql query and clearly SQL doesn't know Regex.Split(). In Linq2Objects you can use that methods since it runs locally. It's important have in mind what LinqTo* you are using.

Avoid extra loop and could not find implementation of query pattern for source type int Select not found

How I can avoid Extra loop and construct order in the LINQ quest itself.
GetOrderListDataContext orderListDaCtx = new GetOrderListDataContext(address);
// This line showing compiler error could not find implementation of query pattern for source type int Select not found
var orderList = from order in orderListDaCtx.Base_Purchase_GetOrderListByUser_WS(request.UserGuid, request.CountryCode, request.FromDate, request.ToDate)
select order;
// Here how i can avoid this loop and construct order object in the LINQ itself above
List<Order> orders = new List<Order>();
foreach (var order in orderList)
{
orders.Add(new Order
{
OrderKey = order.OrderKey,
UserEmail = order.UserEmail,
CreatedDate = order.CreatedDate
});
}
return orders;
Do You mean this?
GetOrderListDataContext orderListDaCtx = new GetOrderListDataContext(address);
var orderList = from order in orderListDaCtx.Base_Purchase_GetOrderListByUser_WS(request.UserGuid, request.CountryCode, request.FromDate, request.ToDate)
select new Order{
OrderKey = order.OrderKey,
UserEmail = order.UserEmail,
CreatedDate = order.CreatedDate
}
return orderList.ToList();
You can just chain:
var orders = orderListDaCtx.Base_Purchase_GetOrderListByUser_WS(request.UserGuid, request.CountryCode, request.FromDate, request.ToDate)
.Select(order => new Order
{
OrderKey = order.OrderKey,
UserEmail = order.UserEmail,
CreatedDate = order.CreatedDate
})
.ToList();
return orders;
This line showing compiler error could not find implementation of
query pattern for source type int Select not found
You main problem is from your stored procedure. Refer: Linq Stored Procedure Issue- Returning an int
See LINQ Error:
Could not find an implementation of the query pattern for source type 'Your.Type'. 'Select' not found. Consider explicitly specifying the type of the range variable
It's likely that orderListDaCtx.Base_Purchase_GetOrderListByUser_WS(request.UserGuid, request.CountryCode, request.FromDate, request.ToDate) returns type 'IEnumerable', but the LINQ requires IEnumerable<T>. You have to perform explicit cast:
var orderList = from Order order in orderListDaCtx.Base_Purchase_GetOrderListByUser_WS(request.UserGuid, request.CountryCode, request.FromDate, request.ToDate)
select order;
I assume, that that Base_Purchase_GetOrderListByUser_WS returns collection of Order.

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