When using SProcs in EF4, I understand the concept of mapping views to entities, then using function imports to map my set/update/deletes to sprocs. The question I have is how this applies to multi tenant architecture. Consider the following scenario:
We have several hundred customers utilizing our multi-tenant database/application. Each customer has somewhere between 50-200 Accounts in the Accounts table. If I expose a view to EF, I cannot parameterize that view. So the following line:
query = (from e in context.Accounts select e).where(e => e.companyID = 1)
[forgive me if I'm syntactically incorrect. still learning EF!]
,by definition, would have to return all of the Accounts first, then filter using my wear clause. is this correct? I can't imagine how else the process would work.
Am I missing something here?
That is the difference between Linq-To-Objects and Linq-To-Entities. Linq-To-Objects operates on IEnumerable<T> and you pass delegates to its methods to define the query which will be executed in the memory. Linq-To-Entities operates on IQueryable<T> and you pass expressions to its methods do define expression tree which is transformed by Linq-to-entities provider into another syntax - to SQL!
So your query will be executed in the database and filtering will be done in the database as well. Be aware that after executing commands like AsEnumerable, ToArray, ToDictionary or ToList you transform the rest of the query to Linq-to-objects.
If you write the query on the result of stored procedure execution you are always doing Linq-to-objects only querying ObjectSets directly forms Linq-to-entities queries.
EF shouldn't be bringing all the accounts back first and then filtering. Rather, it should be be emitting a query with a WHERE clause.
You can check using SQL Profiler, just to be 100% sure.
Related
I have a Ling Query for calculate percentage.
var total = db.Schema_Details.Where(x => x.RID == sName).Select(x => new{
Rid = x.RID,
Amount = Convert.ToDouble(x.Lum_Sum_Amount),
Allocation = Convert.ToDouble(x.Allocation),
total = ((x.Allocation / 100) * x.Lum_Sum_Amount)}).ToList();
But exception occurred.
How can I solve this?
Since you use the identifier db, I assume db is a DbContext. This means that your linq statements will be executed in SQL on the database server side and not in your memory (SQL or something similar, depending on the type of DB your are using).
You can see this if you check the type of your statement in the debugger: is it an IQueryable or an IEnumerable? IQueryables are executed by the database server, IEnumerable are usually executed in your memory. Usually your database server can execute your linq statements faster and more efficient than you, so it is best to make sure your linq statements are IQueryable.
However, the disadvantage is, that you database server does not know any of your classes, functions, nor .NET. So in IQueryables you can only use fairly simple calculations.
If you really need to call some local functions somewhere halfway your linq statement, add AsEnumerable()to your statement:
var myLinqResult = db. ... // something IQueryable
.Where(item => ... ) // simple statement: still IQueryable
.Select(item => ...) // still simple, still IQueryable
// now you want to call one of your own functions:
.AsEnumerable()
.Select(item => myOwnLocalFunctions(item));
See stackoverflow: Difference between IQueryable and IEnumerable
The local function you want to perform is Convert.ToDouble. IQueryable does not know the Convert class, and thus can't perform your function as IQueryable. AsEnumerable will solve this problem.
However, in this case I would not advise to use AsEnumerable. When executing linq statements on a database try to avoid using local classes and function calls as much as possible. Instead of Convert.ToDoubleuse (double)x.Sum_Amount. Your linq-to-sql translator (or similar database language converter) will know how to translate this as IQueryable.
There are some calculations of which there are SQL equivalents, like DateTime calculations, or string reverse. It would be a shame if you had to do things like DateTime.AddDays(1) in local memory while there are perfect SQL equivalents for it. This would especially be a problem if you need to Join, Select or GroupBy after your local functions. Your database server can do these things far more efficiently than you. Luckily there are some IQueryable extension functions for them. They can be found in System.Data.Entity.DbFunctions
Usually the distinction between LINQ to SQL and LINQ to Objects isn't much of an issue, but how can I determine which is happening?
It would be useful to know when writing the code, but I fear one can only be sure at run time sometimes.
It's not micro optimization to make the distinction between Linq-To-Sql and Linq-To-Objects. The latter requires all data to be loaded into memory before you start filtering it. Of course, that can be a major issue.
Most LINQ methods are using deferred execution, which means that it's just building the query but it's not yet executed (like Select or Where). Few others are executing the query and materialize the result into an in-memory collection (like ToLIst or ToArray). If you use AsEnumerable you are also using Linq-To-Objects and no SQL is generated for the parts after it, which means that the data must be loaded into memory (yet still using deferred execution).
So consider the following two queries. The first selects and filters in the database:
var queryLondonCustomers = from cust in db.customers
where cust.City == "London"
select cust;
whereas the second selects all and filters via Linq-To-Objects:
var queryLondonCustomers = from cust in db.customers.AsEnumerable()
where cust.City == "London"
select cust;
The latter has one advantage: you can use any .NET method since it doesn't need to be translated to SQL (e.g. !String.IsNullOrWhiteSpace(cust.City)).
If you just get something that is an IEnumerable<T>, you can't be sure if it's actually a query or already an in-memory object. Even the try-cast to IQueryable<T> will not tell you for sure what it actually is because of the AsQueryable-method. Maybe you could try-cast it to a collection type. If the cast succeeds you can be sure that it's already materialized but otherwise it doesn't tell you if it's using Linq-To-Sql or Linq-To-Objects:
bool isMaterialized = queryLondonCustomers as ICollection<Customer> != null;
Related: EF ICollection Vs List Vs IEnumerable Vs IQueryable
The first solution comes into my mind is checking the query provider.
If the query is materialized, which means the data is loaded into memory, EnumerableQuery(T) is used. Otherwise, a special query provider is used, for example, System.Data.Entity.Internal.Linq.DbQueryProvider for entityframework.
var materialized = query
.AsQueryable()
.Provider
.GetType()
.GetGenericTypeDefinition() == typeof(EnumerableQuery<>);
However the above are ideal cases because someone can implement a custom query provider behaves like EnumerableQuery.
I had the same question, for different reasons.
Judging purely on your title & initial description (which is why google search brought me here).
Pre compilation, given an instance that implements IQueryable, there's no way to know the implementation behind the interface.
At runtime, you need to check the instance's Provider property like #Danny Chen mentioned.
public enum LinqProvider
{
Linq2SQL, Linq2Objects
}
public static class LinqProviderExtensions
{
public static LinqProvider LinqProvider(this IQueryable query)
{
if (query.Provider.GetType().IsGenericType && query.Provider.GetType().GetGenericTypeDefinition() == typeof(EnumerableQuery<>))
return LinqProvider.Linq2Objects;
if (typeof(ICollection<>).MakeGenericType(query.ElementType).IsAssignableFrom(query.GetType()))
return LinqProvider.Linq2Objects;
return LinqProvider.Linq2SQL;
}
}
In our case, we are adding additional filters dynamically, but ran into issues with different handling of case-sensitivity/nullreference handling on different providers.
Hence, at runtime we had to tweak the filters that we add based on the type of provider, and ended up adding this extension method:
Using EF core in net core 6
To see if the provider is an EF provider, use the following code:
if (queryable.Provider is Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider)
{
// Queryable is backed by EF and is not an in-memory/client-side queryable.
}
One could get the opposite by testing the provider against System.Linq.EnumerableQuery (base type of EnumerableQuery<T> - so you don't have to test generics).
This is useful if you have methods like EF.Functions.Like(...) which can only be executed in the database - and you want to branch to something else in case of client-side execution.
I'm looking for answers from a few days ago with no results.
I'm trying to make an implementation of an IRepository interface for generic repository using NHibernate. Here is the interface:
public interface IRepository<TEntity, TKey> where TEntity : BaseEntity
{
TEntity GetById(TKey id);
void Insert(TEntity entidad);
void Update(TEntity entidad);
void Delete(TEntity entidad);
IQueryable<TEntity > Table { get; };
}
I know that there is an extension for the ISession interface, that brings the use of LINQ in my querys, but also I know that that plugin isn't working at 100% (I tested it but when I try to execute some complicated queryes, it thwows not implemented exception, so I can't use that plugin)
I'm using 100% the QueryOver function from the ISession, so.. Do you know any way to implement the IQueroOver function as IQueryable (without launch a "SELECT * " query)? If not, any others ideas for implement the generic repository pattern without use the LINQ extension?
Thank you very much
There's no such thing
Each person has their own definition of what features a 100% implemented LINQ provider should have.
One might expect a LINQ provider to be able to translate String.Equals(String, String, StringComparison) to a SQL expression that uses the correct collation, but unless the programmers who created the LINQ provider programmed it to do so, it's not going to be able to do it.
There is no end to the things we might want a LINQ provider to be able to do, so every LINQ provider has limitations.
There is no such thing as 100% when it comes to LINQ providers.
It is an unattainable concept.
It is infinity.
Thus, it is important to...
know the limitations of your LINQ provider, and
know how to work around those limitations.
Limitations
With NHibernate, knowing the limitations is a bit harder than it should be, because there is currently no official documentation for the NHibernate LINQ provider.
(NH-2444, patches are welcome!)
However, you can figure some of it out just by knowing that this LINQ provider is built on top of HQL, so any limitations that HQL has, LINQ will have as well.
There is no NHibernate query syntax that directly supports performing arbitrary left outer joins on unrelated columns (besides Native SQL, of course).
Queries in NHibernate are designed so that all of the information to perform a join is already stored in the mappings.
After that, all you have to do is specify the relationship, such as order.Customer, and NHibernate knows which tables and columns to join together. You should be able to do arbitrary cross joins using HQL or LINQ, and then you could add a where clause to make it behave like an inner join, but no left outer join.
Since none of the query syntaxes directly support what you want to do, building a LINQ/QueryOver wrapper (as apposed to the existing LINQ/HQL wrapper, and probably just as complex to implement) will gain you nothing.
You'll have to take the same steps to deal with this query whether you're using LINQ or QueryOver.
Workarounds
Since it is not possible for a LINQ provider to be complete, a well designed LINQ provider must be extensible.
That way, if the LINQ provider doesn't natively support the functionality you need, it doesn't ruin your day.
The NHibernate LINQ provider can be extended.
See Giorgetti Alessandro's blog for more information.
But of course, before we go off writing LINQ provider extensions, we should check to see if there's a simpler way to solve the problem.
A couple of possibilities come to mind:
The easiest way to handle this is to simply add the relationship to your NHibernate mappings, enabling you to leverage it in NHibernate queries (LINQ, or whatever).
If the two columns are of incompatible data types, or require some kind of manipulation before you can perform the join, consider fixing the data and the schema in order to enable a smoother mapping.
Another option is to get creative with subqueries or use multiple queries to emulate what your desired join would do. For example, see one of my other answers:
... this LEFT OUTER JOIN can be simulated by combining the results of two separate queries - one to get the orders...
var orders = session.Query<OrderHeader>()
.Fetch(x => x.CreatedBy);
... and another to get the people that have no orders:
var peopleWithNoOrders = session.Query<Person>()
.Where(p => !session.Query<OrderHeader>().Any(o => o.CreatedBy == p));
... because a left outer join is equivalent to an inner join plus additional results for non-matches. I don't know the details of the join you're trying to perform, but hopefully this will give you enough ideas to get started.
Is there a way to create functions for linq to sql that act different when used in linq to entities?
I do not whant to use a AsQueriable. I becouse I whant to do as much calculations on the sql server as possible.
example:
var UserIDs = Users.Select(x=> ConvertToString(x.UserID));
For linq to sql the code has to be:
public string ConvertToString(int id)
{
return SqlFunctions.StringConvert((double?)id);
}
For linq to entities the code has to be:
public string ConvertToString(int id)
{
return id.ToString();
}
You can use SqlFunctions in Entity Framework 4 and above. In your example, you do not have to do the conversion in the application layer.
http://blogs.microsoft.co.il/blogs/gilf/archive/2009/05/23/calling-database-functions-in-linq-to-entities-in-entity-framework-4.aspx
In Linq-to-Entites you won't be allowed to use the ConvertToString call in a query anyway, so this is a brave, but fruitless effort. The reason is that every statement in an L2E query must be an Expression that must be translatable to SQL by the query provider. And (of course) there is no built-in translation for any arbitrary method. L2E is very limited here. It is not even possible to use most native .Net methods like
Users.Select(x=> Convert.ToString(x.UserID)); // NotSupportedException
Linq-to-Sql is a bit more lenient in this. It will run the statement decently. But that does not help you, because you are looking for a common denominator. The bottleneck is L2E and it is a narrow bottleneck.
I do not have a good understandng of how Linq works. I just have tried some examples of Linq that is why I am not sure and have asked the question.
Generally it is said Linq on web is slow. My question is, is Linq with SP give better performance than Linq with Generated SQL ? or both are same.
Please guide.
Because Linq-to-Sql uses a QueryProvider that translates Expressions to SQL statements, it has to do so for every query executed by that provider (unless the query is precompiled [more on that further down]). So, for instance at a basic level:
var people = context.People.Where(p => p.Name == "Matt");
Linq-to-Sql needs to convert the expression p => p.Name == "Matt" into an expression tree, which it in turn converts to a SQL statement, something akin to:
SELECT t0.Name FROM People t0 WHERE t0.Name = 'Matt'
The query when executed against Sql Server, which in turn needs to generate an execution plan for the query and run it against the table to get the results. It's pretty efficient at creating the right query for the right job, and supports more of an ad-hoc approach to data querying.
With stored procedures, Linq-to-Sql doesn't have to generate an expression tree and from that generate the sql, instead the designer generated class has all in information it needs to pass the arguments from the method to the stored procedure.
In that sense, its more efficient to use stored procedures, but you lose the ability to do these ad-hoc queries which are so often useful.
You may find it really comes down to a preference of using sprocs vs. direct queries in your database (discuss this with your DBA).
Compiled queries allow you the benefits of a pre-compiled statement (the query is only generated once), so subsequent queries will use the previously compiled query. An example would be:
public IQueryable<Product> GetProduct(int id)
{
// Normal query, expression tree and sql generated each time it is
// it is executed against the data source.
return context.Products.Where(p => p.Id == id);
}
Whereas a compiled query:
private static readonly Func<DataContext, int, IQueryable<Product>> ProductById =
CompiledQuery.Compile((context, id) =>
context.Products.Where(p => p.Id == id));
public IQueryable<Product> GetProduct(int id)
{
return ProductById(context, id);
}
The latter will use the precompiled query, so it only generates the expression tree and sql once.
Of course, it all depends on your queries and the amount of data you need to fetch.
The more complex your queries get, the less efficient the SQL generated by LINQ will be.
So in case your queries are very complex/ heavy I'd suggest using stored procedures/ views since then you'll be using the power of the DB server instead of less efficient SQL generated by LINQ2SQL.