Mvc: The use of IQueryable and Asqueryable is not clear - asp.net-mvc

I found some lines of code online and I understand the first two lines. Data of a particular
type is cached and stored in the two properties of the models below.
model.payment = (List<CompInfor>)HttpRuntime.Cache[cacheKey + "_received"];
model.FilteredPayment = (List<CompInfor>)HttpRuntime.Cache[cacheKey + "_received"];
However I don't understand the line below as I have never written code like this below.
Please what does this line do? What does it mean? I know you can save a lot of resources by using IQueryable.
IQueryable<CompInfor> payment = model.FilteredPayment.AsQueryable<CompInfor>();

It simply returns an instance of the IQueryable<T> interface which will utilize a query provider to act upon the object in question (in your case, the model.FilteredPayment list). It doesn't seem to make much sense when you're acting against a List locally, but (as an example) in the case of entity framework where you build query statement to be executed against a database via SQL, the Linq to Entities query provider processes the IQueryable into the appropriate SQL statement for execution against the database and processes the results.

Related

How to execute a LINQ to Entities query, pulling values from an existing resultset variable instead of against the DB

To provide some context, I'm using jqGrid to conduct a server side search on a datetime field, truncating the time portion server side, and then fetching results via a stored procedure. This is being done using System.Dynamic.Linq, which I've modified slightly as per this question here. I'm using EF6 Code First approach. The relevant portion of the code looks something like this:
//For matching date instead of datetime values
if (wc.Clause.Contains("Date"))
{
wc.Clause = wc.Clause.Replace("DeliveryDate", "DbFunctions.TruncateTime(DeliveryDate)");
}
results = dataFileDB.Database.SqlQuery<Document>("exec [dbo].[sp_getDocumentDetails]").AsQueryable().Where(wc.Clause, wc.FormatObjects);
The problem I'm having is that because the query is fetched using a stored procedure, I get an exception on the last line saying
System.NotSupportedException: This function can only be invoked from LINQ to Entities.
at System.Data.Entity.DbFunctions.TruncateTime(Nullable`1 dateValue)
In other places where I've used a lambda query to fetch directly from the entity itself and apply the where clause filter, the filtering is done correctly.
What I was trying to do (and I'm not sure if this is possible but...) was run an entity query against the results variable and apply the where clause to that variable but I've had no luck. Is this the right way to go or is there another approach I could take?
Thanks in advance!
Got it... I was overcomplicating things too much.
I just converted the DateTime field to a Date field when returning it via the stored procedure. Doing so no longer required me to use the DbFunctions.TruncateTime method, thereby resolving my issue.
Hope this helps someone else!

Many Duplicate Queries in Entity Framework 5 Code-First(n+1)

One of our contractors implemented a repository pattern with code first approach. We use Service Locator as DI pattern. what we do when we retrieve data from DB, we pass interface to GetQueryable function and get the data. However, I see serious performance issues on our application. I implemented MiniProfiler and MiniProfiler.EF to see where the bottleneck is.
We have a case table which has quite a few fields(around 25) and some of those fields are associated to other tables as one to one and one to many(only one field has many relation to other table). when I try to see the case detail, it runs around 400 SQL queries and SQL takes around 40 percent of the load time as far as the miniprofiler concerned. Here our GetQueryable and Find methods
public IQueryable<T> GetQueryable<T>(params string[] includes)
{
Type type = _impls.Value[typeof (T).Name].GetType();
DbSet dbSet = Db.Set(type);
foreach (var include in includes)
{
dbSet.Include(include);
}
return ((IQueryable<T>) dbSet);
}
I added included to this method to attach other related tables, but it did not make any difference. and here is the Find Method
public T Find<T>(long? id)
{
Type type = _impls.Value[typeof(T).Name].GetType();
return (T) Db.Set(type).Find(id);
}
I pretty much tried to apply all the performance improvements, but the number of the SQL queries has not gone down. I tried to disable lazy loading, but it caused many problems in other parts of the application.
Just some additional information, in case table, there are 70000 rows and in out dialogs table, there are 500000 rows. Case and Dialog are associates as one-to-many. and each case has 20-40 dialog entries.
My questions are;
Why does include not make any difference when I use?
Is there any other way to crop number of the queries run?
Do you think the implementation is the problem?
Thanks
Include returns a new IQueryable and does not modify the source query. In addition you can use the generic version of Set which simplifies the code a bit:
public IQueryable<T> GetQueryable<T>(params string[] includes)
{
IQueryable<T> query = Db.Set<T>();
foreach (var include in includes)
{
query = query.Include(include);
}
return query;
}
Step 1: Fire your contractor. Seriously. Like right now. That is some awful code. Not only did they miss something as simple and basic as using the generic version of Set, but they've successfully only made working with Entity Framework more complex, because all the repository does is proxy Entity Framework methods with its own unique and bastardized API.
That said, there's really not enough here to diagnose what your problem is. The use of Include may give you larger queries, but it should actually serve to reduce the overall number of queries issued. It's possible, you're just not using includes where you should be.
Now, the fact that you "tried to disable lazy loading, but it caused many problems in other parts of the application", means that you're relying too heavily on lazy-loading. Basically, you're loading in stuff you don't even know about, which is the antithesis of optimization. Ironically, you'd actually be best served by going ahead and disabling lazy-loading, and then tracking down where your code fails because of that. If you want to actually lazy-load that thing, you can use .Load (see: Explicit Loading). But, if you want to eager-load to reduce queries, then you know what includes you need to add.

Proper implementation of Repository Pattern using IQueryables?

I'm building a Repository layer for my MVC application with methods like GetObject, UpdateObject, DeleteObject, etc.
This is what I have now:
public List<Object> GetObjects()
{
return _db.Objects.Where(o => o.IsArchived == false).ToList();
}
But I'm wondering if it would be better to return IQueryables for lists so that the least amount of data gets sent to the client when filters are applied in the UoW or Service layers. Would it be best to do something like this?
public IQueryable<Object> GetObjects()
{
return _db.Objects.Where(o => o.IsArchived == false);
}
The not nice thing about returning IQueryable, is that if you ever have a different implementation of repository, say using different ORM, storing data in non-SQL database, cloud or XML file, it would be hard to implement same interface. It would be much easier to implement if you return more generic colections of domain objects. For example IEnumerable. You can always pass filtering criteria in.
The other drawback of returning IQueryable, is that it may happen, that when you actually run the query your object context may be already disposed (Depending on your implementation) or may be kept in memory longer than required.
A leaky abstraction such as IQueryable could cause problems, for example imagine you want to get some data from database and order it by Guid. If you enumerate the query by calling ToList() prior to sorting, you'll get different results if you do it after. The reason is that in first case the sorting will happen in .NET, but in other case it will happen in SQL which uses completely different order.
The nice thing about returning IQueryable here is that you can continue to build up your query further without hitting the db. Once you call ToList it will hit the db and you can't customize your query further without hitting the database a second time.

ASP.NET MVC: Best Way To Call Stored Procedure

I'm trying to decide which is the best way to call a stored procedure.
I'm new to ASP.NET MVC and I've been reading a lot about Linq to SQL and Entity Framework, as well as the Repository Pattern. To be honest, I'm having a hard time understanding the real differences between L2S and EF... but I want to make sure that what I'm building within my application is right.
For right now, I need to properly call stored procedures to: a) save some user information and get a response and, b) grab some inforation for a catalog of products.
So far, I've created a Linq to SQL .dbml file, selected the sotred procedure from the Server Explorer and dragged that instance into the .dbml. I'm currently calling the Stored Procedure like so:
MyLinqModel _db = new MyLinqModel();
_db.MyStoredProcedure(args);
I know there's got to be more involved... plus I'm doing this within my controller, which I understand to be not a good practice.
Can someone recognize what my issues are here?
LINQ and EF are probably overkill if all you're trying to do is call a stored proc.
I use Enterprise Library, but ADO.NET will also work fine.
See this tutorial.
Briefly (shamelessly copied-and-pasted from the referenced article):
SqlConnection conn = null;
SqlDataReader rdr = null;
// typically obtained from user
// input, but we take a short cut
string custId = "FURIB";
Console.WriteLine("\nCustomer Order History:\n");
// create and open a connection object
conn = new SqlConnection("Server=(local);DataBase=Northwind; Integrated Security=SSPI");
conn.Open();
// 1. create a command object identifying
// the stored procedure
SqlCommand cmd = new SqlCommand(
"CustOrderHist", conn);
// 2. set the command object so it knows
// to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which
// will be passed to the stored procedure
cmd.Parameters.Add(
new SqlParameter("#CustomerID", custId));
// execute the command
rdr = cmd.ExecuteReader();
// iterate through results, printing each to console
while (rdr.Read())
{
Console.WriteLine(
"Product: {0,-35} Total: {1,2}",
rdr["ProductName"],
rdr["Total"]);
}
}
Update
I missed the part where you said that you were doing this in your controller.
No, that's not the right way to do this.
Your controller should really only be involved with orchestrating view construction. Create a separate class library, called "Data Access Layer" or something less generic, and create a class that handles calling your stored procs, creating objects from the results, etc. There are many opinions on how this should be handled, but perhaps the most common is:
View
|
Controller
|
Business Logic
|
Data Access Layer
|--- SQL (Stored procs)
-Tables
-Views
-etc.
|--- Alternate data sources
-Web services
-Text/XML files
-blah blah blah.
MSDN has a decent tutorial on the topic.
Try this:
Read:
var authors = context.Database.SqlQuery<Author>("usp_GetAuthorByName #AuthorName",
new SqlParameter("#AuthorName", "author"));
Update:
var affectedRows = context.Database.ExecuteSqlCommand
("usp_CreateAuthor #AuthorName = {0}, #Email= {1}",
"author", "email");
From this link: http://www.dotnetthoughts.net/how-to-execute-a-stored-procedure-with-entity-framework-code-first/
And I would go with the framework David Lively mentioned, instead of having the routines in the controller. Simply pass the results back as IEnumerable<blah> from a function in a separate repository class for an edit, pass a boolean back for if the update succeeded for an update.
LINQ to SQL and ADO.NET EF attach read stored procs to the data/object context class that you use to go against its various entities. For create, update, and delete, you can create a proc that maps the properties of an entity that the model generates, and using the entity mapping window (forget the exact name right now), you can map an entities fields with the proc parameters. So, say you have a Customers table, EF generates a Customers Entity, and you can map the proc parameters to the properties of the Customer entity when attempting to update/insert/delete.
Now, you can map a CUD proc to a function, but I don't know all the repercussions; I like the way I just mentioned the best.
HTH.
I common pattern is to pass a repository interface into your controller by dependency injection. The choice of what persistence/orm technology you use is really another issue and unrelated to the fact that you are using MVC. Using the repository pattern and coding to abstractions (interfaces) makes your application easy to test by mocking out your repositories.
I think you should also try to use as few stored procedures as possible. This means you can more easily test your logic in isolation (unit tests) without needing to be connected to a database. I would highly recommend looking at NHibernate. The learning curve is fairly steep but you are in full control of your mappings and configuration. There are obviously occasions where you will need stored procs for performance reasons, but using an ORM predominantly is very beneficial.
I can't imagine that your goal is to be able to call a stored procedure. To me it sounds as if you need to forget stored procedures and use Linq to Sql. I say L2S because EF is far more to learn, and not needed in this case.

Entity Framework 4: Math.Sin()-function

is there an possibility to call the Math.Sin()-function in a Linq To Entites (Entity Framework 4) -Query?
I've read, that the current Entity Framework 4 doesn't implement this function.
Maybe there's a workaround to this solve problem?
(I don't want to invite all entries in the memory.)
Thanks and best regards
Several functions that (usually) have obvious SQL counterparts, like Math.Sin can't be used directly in Entity Framework queries. Presumably this is because they can't be reliably translated to different SQL implementations. A ton of MSSQL-specific functions are, however, exposed as static methods in the class System.Data.Objects.SqlClient.SqlFunctions. They throw exceptions if you call them directly, but are translated into the proper SQL if used in a LINQ query.
See this blog post about the magic that's happening under the covers (namely the EdmFunction attribute).
It is certainly possible to use such function starting with EF4. In EF4, EF team introduced SqlServer functions that can be consumed in linq. You should alway consider using canonical functions cuz they are database agnostic and every vendor should convert those functions to store specific equivalent. However when such functions are not available, you can resort to SqlServer namespace (ESQL) or SqlFunctions for linq
from l in db.Locations
select SqlServer.Sin(l.Latitude) + SqlServer.power(l.Longitutde)
I cover several of these options in my functions chapter in my book. Specifically you can look at 11-10 recipe Calling database function in esql
11-11 Calling Database Function in LINQ
Unfortunately it's impossible to call Math.Sin in a LinqToEntities query (or Entity SQL query).
The only way to accomplish this without resorting to retrieving all objects first, is to write a SQL query that does what you want and call it via ObjectContext.ExecuteStoreQuery. This isn't as bad as it sounds because you can still get back typed results.
EDIT: After reading the other answers, it appears that it is possible to call these types of functions (SqlFunctions contains 44 functions with various overloads). I leave my original answer as is because it's another way of achieving the same result.

Resources