When using EF6 Database First and trying to execute a stored procedure the auto-generated context adds the required method but sets the return type as ObjectResult. For example the following definition:
public virtual ObjectResult<USP_GetItemDetails_Result> USP_GetItemDetails(int? itemNbr, int? siteNbr)
Has the return type of:
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<USP_GetItemDetails_Result>("USP_GetItemDetails", itemNbr, siteNbr);
Is there anyway to materialize this result as just the concrete class rather than having to send the result as ObjectResult? The next layer in my stack is not aware of Entity Framework.
Turns out ObjectResult under the hood is an IEnumerable. A simple toList means I can return an IEnumerable to the next layer.
Related
I'm developing a database application using Entity Framework 6. In one place, I need to assemble a query based on user input and then return that query to the caller. I can't run the query myself and return the result set because the caller needs to store the query to run again later if the UI is refreshed. I also can't return an IQueryable representing the assembled query because this is only valid for the context against which it was assembled.
I've looked at using CompiledQuery.Compile but this doesn't work with the DbContext base class in Entity Framework 6. I need to do something like that, pre-compiling/pre-assembling/pre-constructing a query that can be returned and run again later, but that works with Entity Framework 6. I don't care whether the query is returned in the form of a delegate or whatever, I just need something that represents the query independently of any specific context instance.
How can I pre-construct and return a query with Entity Framework 6 such that it can be run multiple times against different context instances?
What I ended up doing was creating a delegate type to encapsulate the queries, that takes MyDatabaseContext as a parameter and returns a List<T> where T is the type of the particular entity that I'm querying for.
So now the function that creates the query can simply return a function and whenever the query needs to be run the query is simply called as a function passing it the context instance to act upon as a parameter. The function returns from the given context a list of entities as applicable for the query that it represents.
I have a question about generic list.
Assume that I have a database which contains three tables, User table, Order table and Item table.
In the C# code, I want a function, called GetList to get all he records from one of the three tables.
If I don't use generic method, I have to create 3 different methods which looks like GetAllUsers(), GetAllOrders() and GetAllItems(). Inside these 3 methods, I will have to write the linq to query the database.
My question is how do I implement a generic method.
I want to use EF 4.1. I know how to do it by using NHibrate tho.
UPDATE
What about this? I found it from another post, it can be used to get one single record
public T GetSingleEntity<T>(Expression<Func<T,bool>> expression) where T:class
{
using (PersonalLinksEntities dbContext = new PersonalLinksEntities())
{
return dbContext.CreateObjectSet<T>().SingleOrDefault(expression);
}
}
PersonalLinksEntities is generated by EF, it is database first model.
Here is how I call this method
public ActionResult Index()
{
var thisOne = base.GetSingleEntity<PersonalRecord>(r=>r.RecordID==1);
return View();
}
The specific implementation going to depend on what you are using to access your data. NHib, EF, L2S? These all have some way of accessing an IQueryable generically.
You could expose a method such as:
public IQueryable<T> GetQueryable<T>()
{
//Implementation depends on your data provider
//return dataContext.GetTable<T>();
//return session.Query<T>();
}
But probably what you want to do is follow a repository pattern with a different repository for each type. But you can use an abstract base repository that accepts a type parameter and is reusable.
public abstract class RepositoryBase<T>
{
public IQueryable<T> GetQuery()
{
//Implementation determined by provider
}
}
As there are no details in the question regarding what you have written already. If you just want to GET ALL RECORDS from the tables...Why LINQ...?? You can simply query the database using Data-set and Data-adapter in a method and to make that generic you just pass the table name and get back a Data-set, after that you can play with that Data-set as you like. Please elaborate more if there is any specific complexity in this case which I am missing.
There already exists the method you want on DbContext called Set, e.g. var results = dbContext.Set();
If you are using ObjectContext then the method you want is CreateObjectSet().
When working with stored procedures in linq, I can go to my SP and select what type of entity it should be returning. This works fine in most cases, except the time's I'm not sure of what will be returned. If I don't select what type of entity to return i get the standard
return ISingleResult<SP-Name>
I thought I would be able to work with this return type like this:
List<SP-Name> myResult = context.SP-Name("London");
But this gives me an error offcourse, about implicit converting ISingleResult to List.
How should I do to be able to work with this <SP-Name> returntype?
If you don't specify an entity in your Linq-to-SQL model to be used as the return type for your stored procedure, then Linq-to-SQL autogenerates a type for you.
This is a straight .NET class, so you can inspect its properties and so on - but since it's not one of the entities in you database model, obviously, you cannot save it back to the database and there's no set of that type on your db context, either.
As I said - you can inspect the properties of the return type, you can use that to update other "proper" entities of your Linq-to-SQL model and then save those.
I have a MVC project that has a Linq to SQL dbml class. It is a table called Clients that houses client information. I can easily get the information to display in a View using the code I followed in Nerd Dinner but I have added a stored procedure to the dbml and it's result set is of IQueryable, not IQueryable. I need to convert IQueryable to IQueryable so I can display it in the same View. The reason for the sproc is so I can pass a search string tothe sproc and return the same information as a full list but filtered on the search. I know I can use Linq to filter the whole list but I don't want the whole list so I am using the sproc.
Here is the code in my ClientRepository with a comment where I need to convert. What code goes in the commented spot.
public IQueryable<Client> SelectClientsBySearch(String search)
{
IQueryable<SelectClientsBySearchResult> spClientList = (from p in db.SelectClientsBySearch(search) select p).AsQueryable();
//what is the code to convert IQueryable<SelectClientsBySearchResult> to IQueryable<Client>
return clientList;
}
If your result type and your client type match (IOW, your sproc returns Select * from Client and you haven't modified the Client entity in the DBML since adding it), you can change the stored proc to automtically return IQueryable of Client instead of IQueryable of SelectClientsBySearchResult (see instructions below). Then no conversion is necessary.
If they are different, there are a few different approaches. You can modify the partial class for your entities to add conversion methods to them, or you can use extension methods. Both of these approaches avoid overwriting when the code behind the DBML is regenerated.
To change the stored proc return type:
The DBML designer created the SelectClientsBySearchResult type for your stored proc when you added the stored proc to the DBML. This is the default behavior if you drag the proc from the server explorer to the procedures pane. Instead, drag the stored proc from the server explorer and drop it on the Client table. Now its return type is a collection of Client instead.
I believe you can also change the return type after the fact (as it is now), but I don't have it installed right now and can't guide you through it.
I am trying to get to grips with the Entity framework, and have a requirement to order results by distance from a point on the globe. I have decided on previous advice to do this using a stored procedure which I have successfully done populating a view. However I need to return multiple tables, which I understand I cannot do directly using stored Procedures on the Entity Framework. If this is not correct, I would be grateful if someone could advise how I might do this.
Anyway I therefore have defined a simple sp (SELECT id FROM table) and then wanted to perform a linq query to join this with the equivalent object in my model as follows:
var sp = db.StoredProcedure();
var ret = from x in db.X
join y in sp on x.ID equals y.ID
select x;
However when I perform this I get the following exception resulting from the query:
"Unable to create a constant value of type 'System.Collections.Generic.IEnumerable'1'.Only primitive types('suchas Int32, String, Guid') are supported in this context."
Why is this happening? Is this the right approach? (Note that my final sp will be more complex, and I will be returning multiple classes from the select in 'ret')
Use EF Extensions
Stored procedures are really badly supported in EF. Even if they return entity results, they don't provide any name mappings, so you have to rename columns in stored procedures yourself.
But. There's project called Entity Framework Extensions that will make all kinds of different scenarios with stored procedures possible.
Using EF extensions you can use stored procedures in any way you want:
you can do column remappings in your custom materializer (so your stored procedure returns same columns as they are in the DB without the need to rename columns to entity property names)
you can return multiple result sets (great for 1:* and : relations)
you can use scalar stored procedures or even procedures that don't return anything
you can consume results from a stored procedure that returns multiple entities per row (when having 1:1 relation between two of them)
you can also use output parameters which is great if you create a stored procedure that does paging (returns a subset of records as entities and returns out parameters with total count)
etc.
You can do preety much anything. We've used EF Extensions with much success on a some project. We wrote our own materializers (basically a lamba expression) for entities that our stored procedures returned. And then we materialized their results.
I don't think EF4 will support stored procedures to this level anyway, so getting acquainted to EF Extensions is always valuable.
The EF in .NET 3.5 SP1 cannot map procs which return scalar values (in .NET 4.0 you can). The SP must return all the values necessary to materialize a full entity, which is likely more than just the ID.
Also, it's almost never correct to use the "join" reserved word in LINQ to Entities. You traverse relationships in your client schema instead.
Start by writing a proc which returns all values necessary for an entity type. Map that proc. Then do:
IQueryable<MyEntity> q = from e in Context.MyEntities
select e;
Then move on from there.