Convert string to int in LINQ to Entities? - entity-framework

I have to convert a string value to int, but it seems LINQ to Entities does not support this.
For the following code, I am getting an error.
var query = (from p in dc.CustomerBranch
where p.ID == Convert.ToInt32(id) // here is the error.
select new Location()
{
Name = p.BranchName,
Address = p.Address,
Postcode = p.Postcode,
City = p.City,
Telephone = p.Telephone
}).First();
return query;
LINQ to Entities does not recognize the method 'Int32 ToInt32 (System.String)', and this method can not be translated into a store expression.

Do the conversion outside LINQ:
var idInt = Convert.ToInt32(id);
var query = (from p in dc.CustomerBranch
where p.ID == idInt
select new Location()
{
Name = p.BranchName,
Address = p.Address,
Postcode = p.Postcode,
City = p.City,
Telephone = p.Telephone
}).First();
return query;

No they wouldn't. Think of it this way: both ToString() and Parse() are methods on the objects. Since LINQ to Entities tries to convert your LINQ expression to SQL, those are not available.
If one needs to do this in the query, it might be possible with Cast, which should be available in LINQ to Entities. In the case of ToString, you could use SqlFunctions.StringConvert().

Related

Combinations of Where Criteria - Still parameterized query - Dapper

I have a Dapper query as follows
Public void GetAllCusomers(string CustmoerId, StringFirstName, String LastName, String Gender)
{
TblCustomer tblCustomer = new TblCustomer();
using (var sqlConnection = new SqlConnection(“DatabaseConncetionString"))
{
sqlConnection.Open();
//tblCustomer = sqlConnection.Query<TblCustomer >("SELECT * FROM tblCustomer WHERE CustomerId = #CustomerID" AND FirstName = #FirstName……………, new { CustomerID = CustomerId,……………. }).ToList();
tblCustomer = sqlConnection.Query<TblCustomer >("SELECT * FROM tblCustomer WHERE CustomerId = #CustomerID", new { CustomerID = CustomerId }).ToList();
sqlConnection.Close();
}
}
The question is how to build the query? In the above method user can provide value to any parameters that he wishes to query. If the parameter value is blank that will not be used in the WHERE criteria. I will be using all the supplied parameters in the where criteria with AND operations.
Without Dapper it is easy to build the dynamic query by concatenating the SQL statement depending upon the supplied parameters. How to build these queries in Dapper without compromising the parameterized feature.
Thank you,
Ganesh
string sql = "SELECT * FROM tblCustomer " +
"WHERE CustomerId = #CustomerID AND FirstName = #FirstName"; // ...
var parameters = new DynamicParameters();
parameters.Add("CustomerId", customerID);
parameters.Add("FirstName", firstName);
// ...
connection.Execute(sql, parameters);
You would do it similar to how you build a dynamic query. Build your string dynamically (based on user input), only including filters in the Where clause as needed.
Exmpale:
var query = new StringBuilder("select * from users where ");
if(!string.IsNullOrEmpty(firstname)) query.Append("FirstName = #FirstName ");
As far as passing in the parameters, you can either construct an object that includes all of your possible parameters with values to pass in:
new {FirstName = "John", LastName = "Doe"}
or, if you only want to pass in parameters that will actually be used, you can build a Dictionary<string,object> that contains only those parameters you need to pass in:
new Dictionary<string,object> { {"FirstName", "John" } }

LINQ to Entities does not recognize the method with Let Statement

I am in the process of converting an application that uses LINQ to SQL over to LINQ to Entities. I use a repository pattern and I have run in a problem that works in LINQ to SQL but not Entities.
In my data layer, I use LINQ statements to fill my object graph so that none of my database entities are exposed anywhere else. In this example, I have a Lookup Respository that returns a list of Categories. It looks like this:
public IQueryable<Entities.DomainModels.Category> getCategories()
{
return (from c in Categories
where !c.inactive
orderby c.categoryName
select new Entities.DomainModels.Category
{
id = c.categoryID,
category = c.categoryName,
inactive = c.inactive
});
}
Later, I want to put the categories into a sub query and it looks like this:
var d = from p in Programs
let categories = (from pc in p.Categories
join c in getCategories() on pc.categoryID equals c.id
select c)
select new
{
id = p.id,
title = p.title
categories = categories.ToList()
};
When I run this, I get the following error:
LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[Entities.DomainModels.Category] getCategories()' method, and this method cannot be translated into a store expression.
For reference, the following works though it doesn't return the data I need (it's basically a join):
var q = from p in Programs
from pc in p.Categories
join c in getCategories() on pc.categoryID equals c.id
select new
{
id = p.id,
category = c
};
I understand what the error means in concept however LINQ to SQL would make it work. I have this pattern throughout my data layer and I really want to keep it. Should this be working? If not, how can I modify it without mixing my layers.
You cant pass getCategories() to EF.
The query must be destructible to expression tree.
Calculate getCategories() first.
eg
var simpleList = getCategories().Select(id).Tolist;
then use a contains
where(t=> simpleList.Contains(t.CatId) // or the query syntax equivalent

I get LINQ to Entities Int32 ToInt32(System.String) when convert

I get LINQ to Entities Int32 ToInt32(System.String) when convert.i tried int.Parse() , SqlFunction and EdmFunction but the problem still going on.
Exception:
System.NotSupportedException: LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression
Code:
try
{
ModelEntities me = new ModelEntities();
var query = from p in me.Products
join c in me.ProductCategories
on Convert.ToInt32(p.CategoryId) equals c.CategoryId
select new
{
p.ProductTitle,
c.CategoryName
};
rptProducts.DataSource = query;
rptProducts.DataBind();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
You cannot use Convert.ToInt32 inside your linq query. Linq has its own syntax and does not recognize external methods.
Either you have to extract the variable you are looking for to C#, convert it, and use it as a variable in another query. Or you could make both categoryIDs ints, if you have access to the database. It makes sense that similar fields like those should be of the same type.
Hope that helps!
I suggest converting c.CategoryId to string like this
var query = from p in me.Products
from c in me.ProductCategories
let categoryId = me.ProductCategories.Take(1).Select(x => c.CategoryId).Cast<string>().FirstOrDefault()
where p.CategoryId == categoryId
select new
{
p.ProductTitle,
c.CategoryName
};

string.Join in Linq to Entity queries

I'm currently shifting my data access code from L2S to Entity framework db first. I have problem with queries like following
var emps = (from emp in DataContext.setupEmployees
let contacts = DataContext.setupContacts.Where(x => x.EmployeeID == emp.EmployeeID).Select(x => x.Contact)
select new
{
EmployeeName = emp.EmployeeName,
Contacts = string.Join(", ", contacts.ToArray())
}).ToList();
EF tells me it can't convert the method string.join into stored expression. One obvious work-around is to bring the objects in memory (ToList, AsEnumerable etc) and then call string.Join method like
var emps = (from emp in DataContext.setupEmployees
let contacts = DataContext.setupContacts.Where(x => x.EmployeeID == emp.EmployeeID).Select(x => x.Contact)
select new
{
EmployeeName = emp.EmployeeName,
Contacts = contacts
}).ToList().Select(x=>new{
x.EmployeeName,
Contacts = string.Join(", ",x.Contacts)
});
This solution works perfectly but it's just that it's more verbose and I'd have to duplicate select clause in lots of queries that used to work fine in L2S.
My question: is there any way I can avoid writing this ToList thing and call string.Join and similar methods in EF query?
I would recommend creating Contacts as an IEnumerable<string> datatype instead of string datatype. You can than use Contacts to produce any output you like comma seperated etc...
You can change your query to look like this:
var emps = (from emp in DataContext.setupEmployees
select new
{
EmployeeName = emp.EmployeeName,
Contacts = DataContext.setupContacts.Where(x => x.EmployeeID == emp.EmployeeID).Select(x => x.Contact)
}).ToList();

A LINQ extension that I wrote will not work with Entity Framework

I have an extension method defined like so:
public static TSource MaxBy<TSource, TResult>(this IEnumerable<TSource> collection, Func<TSource, TResult> func) where TSource : class
{
var comparer = Comparer<TSource>.Default;
TSource maxItem = null;
foreach (var item in collection)
{
if (comparer.Compare(item, maxItem) > 0)
maxItem = item;
}
return maxItem;
}
which I then use in the following LINQ-to-Entities query:
var balancesQuery = from t in db.Transactions
where t.UserId == userId
group t by t.CurrencyCode into tg
let tMaxDate = tg.MaxBy(i => i.TsCreate)
join c in db.Currencies on tg.Key equals c.CurrencyCode
select new { Currency = c, Balance = tMaxDate.Balance }
So what I'm doing is - get the newest transaction (MaxBy TsCreate) in each currency (group by CurrencyCode) and then select the balance against each of those transactions.
My problem is - this does not work with Entity Framework (LINQ-to-Entities; I get:
LINQ to Entities does not recognize the method 'Transaction MaxBy[Transaction,DateTime](System.Collections.Generic.IEnumerable'[Transaction], System.Func'2[Transaction,System.DateTime])' method, and this method cannot be translated into a store expression.
The same query works with LINQ to SQL.
My questions are:
Is there a way to make it work with Entity Framework?
Or maybe there is a better way of querying for the same information, which would work with Entity Framework?
Thanks in advance for any help!
Isn't the query same as:
var balancesQuery = from t in db.Transactions
where t.UserId == userId
group t by t.CurrencyCode into tg
join c in db.Currencies on tg.Key equals c.CurrencyCode
select new {
Currency = c,
Balance = tg.OrderByDescending(i => i.TsCreate).Take(1).Balance
};
You can't use extensions with LINQ queries that actually pull data from the database as it's impossible for this to be turned into SQL. However, you can do this by returning the results into memory using ToArray() or ToList() to trigger the database query executing and then call your extension functions on resultant real data in memory.