I have a view that returns data like the following:
1 | Abita | NULL | http://www.abita.com/
2 | Abita | Abbey Ale | http://abita.com/brews/abbey_ale.php
I am using WCF REST to get the xml representation of this view, via an entity framework object. When viewing the returned data as xml in a browser, the first row shows data as I expect:
<vw_Url z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
- <EntityKey z:Id="i2" xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:a="http://schemas.datacontract.org/2004/07/System.Data">
<a:EntityContainerName>FierceBeersEntities</a:EntityContainerName>
- <a:EntityKeyValues>
- <a:EntityKeyMember>
<a:Key>Brewery</a:Key>
<a:Value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Abita</a:Value>
</a:EntityKeyMember>
</a:EntityKeyValues>
<a:EntitySetName>vw_Url</a:EntitySetName>
</EntityKey>
<Beer i:nil="true" />
<Brewery>Abita</Brewery>
<RowId>1</RowId>
<Url>http://www.abita.com/</Url>
</vw_Url>
However, the second row doesn't appear to deserialize the row/object correctly, as it doesn't contain the data from row two.
<vw_Url z:Ref="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" />
Any idea why this might be?
UPDATE:
I've tracked this down to being caused by a UNION within the view. The rows are unioned together from two different tables, and for some reason, EF is treating the second as a reference to the first. Perhaps this is an EF bug? Any ideas for a workaround?
Sounds like this may be an EF bug/limitation in EF 1.0. http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/9293cf4d-deef-40b1-ab56-a0ee1e770dd9 However, I am using EF 4.0 and it still seems to be an issue. Sigh...
UPDATE: I've tracked this down to being caused by a UNION within the view. The rows are unioned together from two different tables, and for some reason, EF is treating the second as a reference to the first. Perhaps this is an EF bug?
Sounds like this may be an EF bug/limitation in EF 1.0. http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/9293cf4d-deef-40b1-ab56-a0ee1e770dd9 However, I am using EF 4.0 and it still seems to be an issue. Sigh...
Related
I've been given a Visual Studio solution to get up and running again for development. The project uses Entity Framework database first. When I generate model from database, the sql wants to convert all of the views into tables. I know views should be avoided with EF, but what is the best way to correct this issue given that the developer no longer works for us?
Thanks
There is nothing wrong with using views with Entity Framework. I assume you mean to say when you update from database it is trying to convert the views to model objects. This is totally fine. often times you are required to specify the primary key for the view. By default Entity Framework will try to use every non null property as the key. in the context menu for each property you can toggle this.
Are you getting an error?
I've come to the conclusion that there is not a way to recreate view entities in your edmx back into actual sql server database views. What needs to happen is that you would generate the sql from the model and run that sql in sql server management studio query analyzer. Delete the tables created that should have been views and figure out what query to write to recreate the views in sql server as they should be. Once that's done, the views in your model should be fine and update there after when running "Update from Database".
Say you have two tables - Categories and Products. You want to create a view called ProductsWithCategoryName. When you do update from database and this view gets added to your EDMX file, viewing the XML shows the following:
<EntitySet Name="ProductsWithCategoryName" EntityType="NorthwindModel.Store.ProductsWithCategoryName" store:Type="Views" store:Schema="dbo" store:Name="ProductsWithCategoryName">
<DefiningQuery>
SELECT
[ProductsWithCategoryName].[ProductID] AS [ProductID],
[ProductsWithCategoryName].[ProductName] AS [ProductName],
[ProductsWithCategoryName].[UnitsInStock] AS [UnitsInStock],
[ProductsWithCategoryName].[CategoryName] AS [CategoryName]
FROM [dbo].[ProductsWithCategoryName] AS [ProductsWithCategoryName]
</DefiningQuery>
</EntitySet>
Problem with the above is that the defining query is NOT the query that creates that view. For you to get the proper defining query you must actually edit the EDMX file by hand adding the proper query to it as follows:
<EntitySet Name="ProductsWithCategoryName" EntityType="NorthwindModel.Store.ProductsWithCategoryName" store:Type="Views" store:Schema="dbo" store:Name="ProductsWithCategoryName">
<DefiningQuery>
SELECT dbo.Products.ProductID, dbo.Products.ProductName, dbo.Products.UnitsInStock, dbo.Categories.CategoryName
FROM dbo.Categories INNER JOIN
dbo.Products ON dbo.Categories.CategoryID = dbo.Products.CategoryID
</DefiningQuery>
</EntitySet>
This still will not give you the expected outcome of a proper sql view getting created. Basically EF when going from the conceptual to the database only produces an table per entity and views are simply seen as another entity.
Recently i upgraded from EF5 to EF6 and here is list of items which one needs to take care of
EF MiniProfiling: if you were using mini profiling with EF5 you will have broken code as few of the functiionality or variable names had been changed.
Resolution: Upgrade to newer version of EF MiniProfiling
Db-Reindexing: After updating to EF6 it complaints you about change in your model and when you do "Add-Migration" you will see all your index for primary key were getting recreated also its changing name of tables where you have one to one relationship so previously if it generates table name as TableATableB then it will rename table as TableBTableA dont know why.
Resolution 1: Let EF create migrations for create index , just comment out line in
up and down function.
Resolution 2: Copy line of code from down function(i.e. drop index) and try to execute it before it create index , simple rule first drop and then create, you need this else EF will complaint about index already present.
Migrations: This will only affect you if you are doing using some tool to deploy you assemblies and which in turns uses migrate.exe typically found at
...#your project location\packages\EntityFramework.6.1.0\tools\migrate.exe
copy it to your bin folder and things should work fine.
4. Null Handling: In EF6 handling of null values had been changed , my hands on experience says that with ef5 select query was ignoring null cases but is not the case with ef6
e.g. if i have query something like
db.context.entity.where(name != "ab");
and lets say entity table contains two names {"ab",null}
with EF5 it will return 1 row with ef6 it was returning 2 rows
http://entityframework.codeplex.com/workitem/2115
Resolution: If you wanted to work exactly like EF5 you can set
dbContext.Configuration.UseDatabaseNullSemantics = true;
If it helps please don't forgot to mark this post as answered :)
None of the many questions on this topic seem to match my situation. I have a large data model. In certain cases, only a few of the fields need be displayed on the UI, so for those I replaced the LINQ to Entity query that pulls in everything with an Entity SQL query retrieving only the columns needed, using a Type constructor so that I got an entity returned and not a DbDataRecord, like this:
SELECT VALUE MyModelNameSpace.INCIDENT(incident.FieldA, incident.FieldB, ...) FROM ... AS ...
This works and displays the fields in the UI. And if I make a change, the change makes it back to the entity model when I tab out of the UI element. But when I do a SaveChanges, the changes do not get persisted to the database. No errors show up in the Log. Now if I very carefully replace the above query with an Entity Sql query that retrieves the entire entity, like this:
SELECT VALUE incident FROM MyDB.INCIDENTs AS incident...
Changes do get persisted in the database! So as a test, I created another query like the first that named every column in the entity, which should be the exact equivalent of the second Entity SQL query. Yet it did not persist changes to the database either.
I've tried setting the MergeOption on the returned result to PreserveChanges, to start tracking, like this:
incidents.MergeOption = MergeOption.PreserveChanges;
But that has no effect. But really, if retrieving the entire entity with Entity Sql persists changes, what logical purpose would there be for behaving differently when a subset of the fields are retrieved? I'm wondering if this is a bug?
Gert was correct, the problem was that the entity was not attached. Dank U wel, Gert! Ik was ervan verbluft!
I just wanted to add a little detail to show the full solution. Basically, the ObjectContext has an Attach method, so you'd think that would be it. However, when your Entity SQL select statement names columns, and you create the object using a Type as I did, the EntityKey is not created, and ObjectContext.Attach fails. After trying and failing to insert the EntityKey I created myself, I stumbled across ObjectSet.Attach, added in Entity Framework 4. Instead of failing, it creates the EntityKey if it is missing. Nice touch.
The code was (this can probably be done in fewer steps, but I know this works):
var QueryString = "SELECT VALUE RunTimeUIDesigner.INCIDENT (incident.INCIDENT_NBR,incident.LOCATION,etc"
ObjectQuery<INCIDENT> incidents = orbcadDB.CreateQuery<INCIDENT>(QueryString);
incidents.MergeOption = MergeOption.PreserveChanges;
List<INCIDENT> retrievedIncidents = incidents.ToList<INCIDENT>();
orbcadDB.INCIDENTs.Attach(retrievedIncidents[0]);
iNCIDENTsViewSource.Source = retrievedIncidents;
I'm simply trying to get data from two sql server db tables using ado.net entity framework. My code is:
using (Model.Entities e = new Model.Entities())
{
return e.PAGE.First().CONTROL;
}
The database is setup to have two tables, a control table which links to a page table via an 'id' field in the tables (control_id). There is one CONTROL object for each PAGE object.
I keep getting a null value for my return value and I know that's not right.
I can use vis studio and breakpoints to see that there is a PAGE object in 'e' and I can see that there are multiple CONTROL objects in 'e'. This isn't a large database, I just have some sample data in there to ensure that I get this working - so I know that there should be a CONTROL object connected to this PAGE (i've verified this through sql server).
I am very familiar with the general code syntax, I've been using LINQ for a couple of years; however, I have not done much work at all with the entity framework or ado.net 4.
It seems like if I just pull individual table data then it works fine (i.e. e.PAGE.First() .. or .. e.CONTROL.Where(x=>x.someValue.Equals('someValue') ) but if I try to pull by traversing through the tables then I get nothing back (NULL).
Hope that all makes sense.
Some questions for you:
I assume is a 1..1 between PAGE and CONTROL,
Is there a FK called "ControlID" on PAGE?
Do you have a navigational property called "Control" on your "Page" entity in your EDMX?
If the answer to all of the above is Yes, then this should work:
var page = e.Pages.Include("Control").First();
Here, you are returning the First "Page" record, and eager loading the associated control.
The SQL produced should be something like this:
SELECT p.*, c.*
FROM Page p
INNER JOIN Control c
on p.ControlId = c.ControlId
I'm new to EF, and trying to work out the best way to do something
I have a procedure that returns the details of a table, but also a calculated value. What I'd like is for it to return this information to an entity that could contain this, whether it's the original entity, or an entity that's based on the original (so that if the original table changes, it will still map). What I'd like to avoid is maintaining 2 entities - 1 for the table, and 1 for the stored procedure results.
Thanks...
You could create a view that contained the table fields as well as the calculated values.