I have an Oracle database which contains some tables with no foreign or primary keys on them. I will create some stored procedures to handle the interaction with these tables, takes some parameter and return some values.
I would like to create an asp.net MVC app using EF and deal with this database using only the stored procedures. I don't want to bring any of the tables to the app as entities or anything.
I have been googling this, but all I can find is examples where the tables(entities) themselves are in the EDM and the stored procedures are being added to them for the interaction.
EX:
Is it possible to get the EF to deal with stored procedures only and provide me with models based on these stored procedures? if yes would you please direct me to the right materials?
Thanks,
You can use ExecuteStoreQueryList or equivalent on dbContext directly, create dto model result returned.
A sample:
using (var ctx = DataContext())
{
return ctx.ExecuteStoreQueryList<MyModel>(
"EXEC dbo.[xxx] #xxx, #xxx, #xxx, #poleID, #xxx",
new SqlParameter("xxx", xxx),
new SqlParameter("xxx", xxx),
new SqlParameter("xxx", (object)xxx?? DBNull.Value),
new SqlParameter("xxx", (object)xxx?? DBNull.Value),
new SqlParameter("xxx", (object)xxx?? DBNull.Value)
);
}
Related
Is it possible to add a column (or execute some SQL) to a table when Entity Framework is instantiating a new database, without defining it in the Model used in DbSet ?
Iam building a prototype for a SaaS application with Entity Framework and Elastic Scale Client, and want to use Row Level Security, for that a need a column to identify my tenants. So i figured it would be nice if I could use just the EF initializer to add this column, when adding new tenants to the system.
As noted in the documentation here, you can execute sql when you have the DBContext.
From the docs:
using (var context = new BloggingContext())
{
context.Database.ExecuteSqlCommand(
"UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");
}
You could use this to modify the structure without having the actual structure defined in EF.
I am working on an ASP.NET MVC 4 web application. I am using Entity Framework as the data access layer, using database first approach (.edmx file).
Currently I have a problem in join tables that are defined inside two different databases (i.e. I have two .edmx files).
For example if I want to join tables I am performing the following query:-
public ActionResult AutoComplete(string term)
{
var tech = repository.AllFindTechnolog(term).Take(100);//Call to the first database
var resources = repository.GetResources(tech.Select(a => a.IT360ID.Value).ToArray(), false);//call to the second database
var query = from techItems in tech
join resourcesItems in resources
on techItems.IT360ID.Value equals resourcesItems.RESOURCEID // join based on db2ID
orderby techItems.PartialTag
select new //code goes here
return Json(query, JsonRequestBehavior.AllowGet);
}
I will have two separate calls to the database, and a join inside the application server, which is not the best performance-oriented solution. Ideally the joins will happen completely inside the database engine.
I know that a stored procedure will allow me to join tables from different databases purely on the server, but I do not want to use SP because it will make my code less maintainable and less testable.
So I am searching for a solution where I can do the join using entity framework and to result in a single database join?
If you want to do it with a single database call you will have to create a View in the database that joins the 2 tables from separate db's. Once the view is created you can add it to EF as a single object, which you can manipulate further and Query off of. The view will basically be a table and it will be easily maintable and easy to bind to a strongly typed model
Another way ,similiar like you have posted, you can query separate .edmx files and then join them.
Yes, there is 2 calls to the database but it shouldn't be that expensive and probably won't notice a difference.
using(var db = new MyEntities())
using (var db2 = new MyEntities2())
{
var one = db.Table1.AsEnumerable();
var two = db2.Table2.AsEnumerable();
var result = from o in one
join t in two on o.Id equals t.Id
// blah blah
}
#CSharper's answer is close. As #Oliver mentioned in the comments, IEnumerable loads the table into application memory, leading to crashes if you have a large database.
The solution is to use IQueryable, which can be called with LINQ - this produces SQL which is much faster.
// This is a generic method, modify to your needs
public ActionResult Details(int? id)
var one = db.Table1.AsQueryable();
var two = db2.Table2.AsQueryable();
// since you're using MVC EF, I assume you want to put this in a viewmodel
// (in this case ObjectCombined)
// assume "id" is passed as parameter
Object1 result1 = (from o in one where one.id == id select o).Single();
Object2 result2 = (from t in two where t.id == o.id select t).Single();
ObjectCombined result = new ObjectCombined(result1, result2);
return View(result);
}
Might I suggest that you look into using a synonym in your database. For instance, you can create a synonym to the resources table in the database that your tech table is located. This will ensure that you will not need to maintain 2 EDMX files. Instead you can have a single EDMX file and you can simply join your tech table to the synonym of the resource table and voila - you are on your way.
UPDATE: Please note that if you are using synonyms there is an extra bit of work you will need to do to the EDMX file to get it working in Entity Framework. Here is a blog post that was put out by a programmer who got it to work. Here is the original stackoverflow question she asked.
HAPPY CODING!!! :)
you can create a view or a stored procedure, your sql statement can then make cross db query just make sure your credentials can DML or DDL on both db. otherwise try the nested using entities that will make sure you will not get the linq bug when you dont declare the db entity inside a using statement.
Is there actually any official strategy for creating and using views with EF6.1 Code First? I can reverse the database into Code First and get tables not views. I can import the database into Model First and get views and then do Generate DB from Model and my edmx is modified and the views are converted to tables. MSFT seems to have all but abandoned Model First, and the new Update 2 seems to have reverse engineering for Code First so I feel forced to convert to Code First but has the EF team given support for any reasonable approach to using views or stored Procedures in Code First? After all CF is supposed to create the DB but what - are you no longer supposed to use either of these SQL Server features in a .NET EF application?
For starters you can use views and stored procedures that are already created in the database. For views you don't have to do any mapping if you create a code like this:
public TestContext : DbContext
{
public DbSet<User> AdminUsers { get; set; }
}
And you have a view in the database named dbo.AdminUsers and it can be mapped to the class User (contains all required properties with the same name as the property).
For stored procedures you can use the SqlQuery function either through the Database property of the DbContext such as:
var userActivityReport = context.Database.SqlQuery<UserActivityReport>(
"dbo.GetUserActivityReport #p0, #p1", startDate, endDate);
Or through the SqlQuery function of the DbSet class:
var newUsers = context.Users.SqlQuery("dbo.GetNewUsers #p0", count);
If you want to create, modify or delete views and stored procedures via Entity Framework you can either use custom migration operations see http://dolinkamark.wordpress.com/2014/05/03/creating-a-custom-migration-operation-in-entity-framework/
For event better integration you can use the Public mapping API with a library provided by a community member: https://codefirstfunctions.codeplex.com/
Getting an error client side with breeze: "Cannot call method 'map' of undefined" when trying to pull over some data. The difference between this action and one that works is that this action is calling a stored procedure and returning ObjectResult<T> instead of DbSet<T>.
Might this be why I get an error? Using Chrome Developer tools, I do see that the breeze controller is returning json data.
I have created a complex model type in the edmx for mapping the rows returned from the stored procedure.
The action in the breeze controller has a return type of IEnumerable<T>.
I experienced the same error when using an EF complex type. A workaround was to create a view in my database instead of using a complex type, set the stored procedure to return a type of the new view which had a primary key and then it worked. It would seem that breeze requires entities to have a primary key defined.
Hm... not quite sure what is happening, so just guessing here, but try adding an AsQueryable() to the result returned, and changing the result type to a IQueryable.
We don't have any stored proc tests for breeze yet, but this is impetus for me to add some :)
I had the very same issue, but thank God I figured out a solution. Instead of using a stored procedure, you should use a view, as Breeze recognizes views as DbSet<T>, just like tables. Say you have a SQL server table that contains two tables Customers and Orders.
Customers (**CustomerId**, FirstName, LastName)
Orders (OrderId, #CustomerId, OrderDate, OrderTotal)
Now, say you want a query that returns orders by CustomerId. Usually, you would do that in a stored procedure, but as I said, you need to use a view instead. So the query will look like this in the view.
Select o.OrderId, c.CustomerId, o.OrderDate, o.OrderTotal
from dbo.Orders o inner join dbo.Customers c on c.CustomerId = o.CustomerId
Notice there is no filtering (where ...). So:
i. Create a [general] view that includes the filtering key(s) and name it, say, OrdersByCustomers
ii. Add the OrdersByCustomers view to the entity model in your VS project
iii. Add the entity to the Breeze controller, as such:
public IQueryable<OrdersByCustomers> OrdersByCustomerId(int id)
{
return _contextProvider.Context.OrdersByCustomers
.Where(r => r.CustomerId == id);
}
Notice the .Where(r => r.CustomerId == id) filter. We could do it in the data service file, but because we want the user to see only his personal data, we need to filter from the server so it only returns his data.
iv. Now, that the entity is set in the controller, you may invoke it in the data service file, as such:
var getOrdersByCustomerId = function(orderObservable, id)
{
var query = breeze.EntityQuery.from('OrdersByCustomerId')
.WithParameters({ CustomerId: id });
return manager.executeQuery(query)
.then(function(data) {
if (orderObservable) orderObservable(data.results);
}
.fail(function(e) {
logError('Retrieve Data Failed');
}
}
v. You probably know what to do next from here.
Hope it helps.
New to Entity Framework .Using EF4. I have found articles and managed to use stored procedures to return a list of entities.
But cannot see/work out how you return a single entity.
Given that I have a stored procedure "GetCustomerById" that return a single customer How do I map it?
Using the Model Browser I right click on "Function Import" and I have added my StoredProcedure
however whatever I select does not seem to return a "Single Entity"
Am I missing the obvious?
thanks a lot for any link or suggestions
When you do Function Import you need to select the entity your SP returns from the drop down (i.e. Customer). The catch is EF does NOT directly returns Customer object as per your selection but System.Data.Objects.ObjectResult which implements IEnumerable.
To be more specific, here is the generated code for your function:
public ObjectResult<Customer> GetCustomerById(Nullable<global::System.Int32> Id)
That's because EF has no idea if your SP returns a single record or a list of them so it wraps the result inside ObjectResult. You can enumerate through this to get your Customer entity like any other IEnumerable object. For example:
Customer myCustomer = context.GetCustomerById(1).First();