How to user "merge" in entity framework code first to merge the multiple result set from a stored procedure into one single collection - entity-framework

I am new to entity framework. I have a simple stored procedure that returns 2 result set.
I am using a code-first approach and need to merge the 2 result set into one single collection using "merge". I don't want to modify my stored procedure.
Any help would be appreciated. Thank you.

Just follow the doc here:
Entity Framework Sprocs with Multiple Result Sets
Except in your case both DataReaders load the same entity.
eg
var foos1= ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Foo>(reader, "Foos", MergeOption.AppendOnly);
// Move to second result set and read next set of entities
reader.NextResult();
var foos2 = ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Foo>(reader, "Foos", MergeOption.AppendOnly);
var foos = foos1.Union(foos2).ToList();

Related

Retrieving some columns from database with Breeze.js, and still be able to update database

I am new to Breeze.js, but really enjoy it so far. I ran into an issue with updating a database with Breeze.js, when selecting only portion of columns of a model.
When I ran this statement:
$scope.emFac.entityQuery.from('Company');
the company entity matches my EF entity, retrieves all columns, creates entityAspect, and all is working fine when updating database:
However, when I retrieve only portion of corresponding Model's columns, Breeze.js returns anonymous object with specified properties (retrieving data works, but not updating does not), without the entityAspect, which is being used for tracking changes.
Here is the code with select statement:
$scope.emFac.entityQuery.from('Company').select('companyId, displayName');
Is there a way to retrieve only some columns of EF Model columns, and still track changes with Breeze.js, needed for database updates?
As you've discovered, Breeze treats the incoming data as plain objects instead of entities when you use select.
Your choices are:
On the server, Create a CustomerLite or similar object, and have a server endpoint that returns those without the need for select; OR
On the client, get the results from the query and create entities from each object, with status Unchanged
Example of #2:
var entities = [];
em.executeQuery(customerProjectionQuery).then(queryResult => {
queryResult.results.forEach(obj => {
// obj contains values to initialize entity
var entity = em.createEntity(Customer.prototype.entityType, obj, EntityState.Unchanged);
entities.push(entity);
});
})
Either way, you will need to ensure that your saveChanges endpoint on the server can handle saving the truncated Customer objects without wiping out the other fields.

How can I get the SqlDbType or DbType from IModel in EntityFramework Core 2?

My use case is:
I have a graph of objects from many entities in Entity Framework Core 2 (EFC 2). In EFC 2, the SaveChanges Operation is very slow. The reason appears to be the limit in number of parameters that Sql Server can receieve per query. As Sql Server receive 2100 parameters per query, saving hundreds of thousands of registers must cause many roundtrips, with much latency implied. See issue 2484 for more information. My current solution is to generate a SqlCommand with a query with Table Valued Parameters (TVP). The plan is to use only one query with a TVP for each table and operation (insert, update and delete), using only one roundtrip for save all the changes. EFC cannot do that actually.
In theory, i'm almost finish this, but i have a problem. To use TVP, i must get the SqlDbType for each column from my Table Type. The Table Types are generated using the metadata in the IModel from EFC. But, i cant get the SqlDbType. Simplified, I tried with:
var typeMapper = new SqlServerTypeMapper(new RelationalTypeMapperDependencies());
var entityType = context.Model.GetEntityTypes().First();
var prop = entityType.GetProperties().First();
var mapping = typeMapper.GetMapping(prop);
var dbType = mapping.DbType;
Having dbType, the plan is get the SqlDbType from dbType using a Dictionary. The problem is dbType is getting null.
I'm searched in the api, and i can get the way to extract a SqlType from IModel. Is this possible?

EF 4.1 Code First Raw SQL

I would like to return entities using RAW SQL, so I have the following code which returns a set of Entities:
var rawSql = "exec spFindStories #pattern, #page, #pageSize";
// use raw SQL because SP is needed
// results are not tracked.
var stories = context.Database.SqlQuery<Story>(rawSql,
new SqlParameter("#pattern", pattern),
new SqlParameter("#page", page),
new SqlParameter("#pageSize", pageSize)
).ToList();
Now for each one of these stories, I need to load their related Tags. It seems that CF does not load related entities returned in the results. How can I achieve this ??
Thanks!!
Why not add it as a function import and specify what it's returning as the entity you expect?

Adding & Removing Associations - Entity Framework

I'm trying to get to grips with EF this week and I'm going ok so far but I've just hit my first major snag. I have a table of items and a table of categories. Each item can be 'tagged' with many categories so I created a link table. Two columns, one the primary ID of the item, the other the primary ID of the category. I added some data manually to the DB and I can query it all fine through EF in my code.
Now I want to 'tag' a new item with one of the existing categories. I have the category ID to add and the ID of the Item. I load both as entities using linq and then try the following.
int categoryToAddId = Convert.ToInt32(ddlCategoriesRemaining.SelectedValue);
var categoryToAdd = db.CollectionCategorySet.First(x => x.ID == categoryToAddId);
currentCollectionItem.Categories.Add(categoryToAdd);
db.SaveChanges();
But I get "Unable to update the EntitySet 'collectionItemCategories' because it has a DefiningQuery and no element exists in the element to support the current operation."
Have I missed something? Is this not the right way to do it? I try the same thing for removing and no luck there either.
I think I have managed to answer this one myself. After alot of digging around it turns out that the Entity Framework (as it comes in VS2008 SP1) doesn't actually support many to many relationships very well. The framework does create a list of objects from another object through the relationship which is very nice but when it comes to adding and removing the relationships this can't be done very easily. You need to write your own stored procedures to do this and then register them with Entity Framework using the Function Import route.
There is also a further problem with this route in that function imports that don't return anything such as adding a many to many relationship don't get added to the object context. So when your writing code you can't just use them as you would expect.
For now I'm going to simply stick to executing these procedures in the old fashioned way using executenonquery(). Apparently better support for this is supposed to arrive in VS2010.
If anyone feels I have got my facts wrong please feel free to put me right.
After you have created your Item object, you need to set the Item object to the Category object on the Item's Categories property. If you are adding a new Item object, do something like this:
Using (YourContext ctx = new YourContext())
{
//Create new Item object
Item oItem = new Item();
//Generate new Guid for Item object (sample)
oItem.ID = new Guid();
//Assign a new Title for Item object (sample)
oItem.Title = "Some Title";
//Get the CategoryID to apply to the new Item from a DropDownList
int categoryToAddId = Convert.ToInt32(ddlCategoriesRemaining.SelectedValue);
//Instantiate a Category object where Category equals categoryToAddId
var oCategory = db.CategorySet.First(x => x.ID == categoryToAddId);
//Set Item object's Categories property to the Category object
oItem.Categories = oCategory;
//Add new Item object to db context for saving
ctx.AddtoItemSet(oItem);
//Save to Database
ctx.SaveChanges();
}
Have you put foreign keys on both columns in your link table to the item and the category or defined the relationship as many to many in the Mapping Details?

Entity framework function import, can't load relations for functions that return entity types

I've created a function import that returns the results of a stored proceedure as one of my entities. however I can't seem to traverse my through navigation properties to access the data in other entities. I know that you can use include() for objectQueries but can't find anything that will force the EF to load my relations for entity results of function imports.
Any ideas??
Thanks in advance.
This is not possible in EF 1.0
The reason is that EF will consider stored procedure values to be just values and not navigation properites.
For example, Employee entity has multiple Order entities. In Order you have a property called EmployeeID. When the database fills your query using include statements, it creates 1 projection query in SQL to populate all of the Order data that a particular Employee could have.
So if I said
var employee = context.Employees.Include("Orders").Where(e => e.ID == 1).First();
var orders = employee.Orders;
The SQL for the first query will create a projection query which will contain orders where the EmployeeID = 1.
Now when your stored procedure runs, this can do any code behind the scenes (in otherwords it can return any set of data). So when SQL runs the stored procedure, it just runs the code in that stored procedure and does not have any knowledge that EmployeeID on Order is an FK to that property. Additionally, if your stored procedure returns an Employee entity, then you are looking at another scenario where you will not even have an OrderID to pursue.
To work around this though, you can setup your query in EF using Include statements that can mirror any stored procedure. If you use the proper mix of .Select and .Include statements you should be able to do the same thing.