Why can't I use a View containing a Union in Entity Framework 4.0? - entity-framework

I have a View which looks similar to this:
SELECT Id, Name
FROM Users
UNION ALL
SELECT NULL as [Id], NULL as [Name]
When I try to map to this view in Entity Framework, it just fails. I don't get an error, but the view does not exist in my data store. Why is this? Is there a way around it?

I know this is an older question already marked as answered, but I wanted to post an alternative to editing the edmx. I learned this one the hard way, after tons of Google searches and pulling my hair out for hours, trying different options...
For a view, EF attempts to to infer a primary key by identifying columns that are non-nullable
and non-binary (see Create an Entity Key When No Key Is Inferred).
With a view used to flatten related data for lookup purposes, this can result in many columns (or the wrong ones) being inferred as keys.
For a view with a UNION, it can cause the opposite problem, because there may be no true identity column that can be safely included as a key.
To force EF to identify columns as a key, you can use ISNULL() to ensure the value is non-nullable: ISNULL(column_name, replacement_value)
To force EF to not mark a column as a key, you can use NULLIF() to make it nullable: NULLIF(column_name, value_not_equal_to_parameter_1)
If you need to ensure a value is returned, but don't want to have it marked as a key, I believe COALESCE(column_name, replacement_value) will do the job of ISNULL without EF marking the column as a key
If there is truly no viable column available as a primary key (as in a UNION view), you can fake a non-nullable PK through the use of ISNULL() combined with ROW_NUMBER() in your SELECT statement: SELECT ISNULL(ROW_NUMBER() OVER (ORDER BY sort_criteria), 0) as 'ALIASNAME'
As an alternative, the edmx can absolutely be edited directly as Marcos Prieto suggested, but you run the risk of having those changes overwritten the next time you run "Update Model from Database".
Hope this helps anyone who encounters this in the future!

It is because Visual Studio cannot infers the Primary Key of your View.
You can see the error message within edmx file by open it with XML editor and see the SSDL section.
Here is error message that results from my Model(which I created some View like yours within my Database just to emulate) :
Errors Found During Generation:
warning 6013: The table/view 'PhoneBook.dbo.ContactCustomer' does not have
a primary key defined and no valid primary key could be inferred.
This table/view has been excluded. To use the entity,
you will need to review your schema,
add the correct keys, and uncomment it.
It is not true that Union is not supported in EF 4.
But I think the problem is that Visual Studio saw your view as the odd View.
You can doing some experiment by create another View and compares them (using update model from database menu within model designer).
And you can modify the Model by hand (manual typing the edmx file) to define the Primary Key to resolve this.

I had a view that worked perfectly. I modified it (changed the view on a union of 2 tables), updated the model from database and this problem appeared.
I fixed it in 3 steps:
Open the .edmx file with a XML editor.
Uncomment the view's EntityType XML (edmx:StorageModels > Schema) code and add the Key:
<EntityType Name="your_view">
<Key>
<PropertyRef Name="your_id" />
</Key>
<Property Name="your_id" Type="int" Nullable="false" />
<Property Name="other_field" Type="varchar" MaxLength="45" />
</EntityType>
Be sure that EF didn't erased the view in edmx:StorageModels > Schema > EntityContainer (if you have code repository, copy the code from there):
<EntitySet Name="your_view" EntityType="Your_Model.Store.your_view" store:Type="Views" store:Schema="your_schema" store:Name="your_view">
<DefiningQuery>SELECT
`your_view`.`your_id`,
`your_view`.`other_field`,
FROM `your_view` AS `your_view`
</DefiningQuery>
</EntitySet>

I know this is an old question but i faced this issue recently & after trying to do the above mentioned methods i simply created another view that selects from the Union view & i was able to map the new view by updating my entity model.

Related

Adding a New Column to an Existing Table in Entity Framework

I have added a new column to a table in my database. The table is already defined in the existing Entity Framework model. I've been through most of the items here on how to do this and it still fails.
A little background, this entity model has not been updated in at least 3 years. So aside from the column I'm adding I know there have been a number of other columns that have been added in that time, but never included. I took over the project about 9 months ago and have never been able to successfully update the model.
First attempt:
Opened the Model in Visual Studio
Right Clicked on the Background
Clicked on "Update Model From Database..."
Clicked on the Refresh Tab
Selected Tables
Highlighted the specific table
Clicked Finish
Result:
Classes for Dozens of tables that were in my model were deleted
The table in question was not updated
Second Attempt
Restored all Source
Same as above but
After opening the Update Wizard, Clicked the Delete Tab
Selected Tables
Clicked Finish
All the Tables were deleted
Saved the EF Model/Closed/Opened it
Went back to the Update Wizard Add Tab
Clicked Tables
None of my tables were displayed when I expanded everything
Checked the checkbox at the Tables level
Result
None of my tables were added back, but anything that was not
originally included was added
Third Attempt
Restored all source
Deleted the two .tt files
Opened the Update Wizard
Clicked Add for Everything
Result
Nothing was recreated, no .tt files or anything else.
Fourth Attempt
Restored Source
Deleted Table from the EF Model
Opened Update Wizard
Clicked Add Tables
Results
Classes for Dozens of tables that were in my model were deleted
The table in question was not added back
Final Attempt
Added entity manually to model
Result
Code all compiled and ran, but values were never retrieved from the DB or updated
Any help or direction that could be provided would be greatly appreciated as I'm at a critical point and have to get the model updated.
The "Update Model from Database" is hard/slow to use and is prone to errors. It generates other stuff that you probably don't want/need. So manually adding the column that you need will work better.
I suggest you do it outside the VS editor since depending on how many models/tables, it can be very slow opening the file in VS.
So in Windows Exlorer, right-click on the *.edmx file and open with Notepad (or Notepad++/Textpad).
Search for the text <EntityType Name="YourTableNameToAddColumn">.
Add the property <Property Name="YourNewColumnName" Type="varchar" MaxLength="64" />
Search for the text <MappingFragment StoreEntitySet="YourTableNameToAddColumn">
Add mapping to the new column <ScalarProperty Name="YourNewColumnName" ColumnName="YourNewColumnName"/>
Save the *.edmx file
Right click on the *.edmx file and open with Visual Studio's XML editor (or Notepad/Notepad++/Textpad).
Search for the text <EntityType Name="YourTableNameToAddColumn">.
Add the property e.g.: <Property Name="YourNewColumnName" Type="varchar" MaxLength="64" /> (these ones are SQL types, see existing columns for an example of how they should look).
Search for the text again <EntityType Name="YourTableNameToAddColumn">, there is a second one.
Add the property e.g.: <Property Name="YourNewColumnName" Type="String" MaxLength="64" FixedLength="false" Unicode="true" /> (these ones are EF types, see existing columns for an example of how they should look).
Search for the text <MappingFragment StoreEntitySet="YourTableNameToAddColumn">.
Add mapping to the new column <ScalarProperty Name="YourNewColumnName" ColumnName="YourNewColumnName"/> (Note: these are in reverse order, newest first)
Save the *.edmx file
After that update the edmx model of your table in the (auto-generated) entity framework .cs files public string YourNewColumnName { get; set; }
An addendum to the answer by alltej above, and answering Chris Walsh's reply that he is getting 'The conceptual side Member or Property 'xxxxx' specified as part of this MSL does not exist in MetadataWorkspace." on the new Scalar property line under '
You have to make sure that you search 'Add the property ' in TWO places within your .edmx file , otherwise you will get Chris's error
Figured out the problem. When I generated the model I was getting an Error 113:
Multiplicity is not valid in Role.
I didn't notice it among the other 16307 errors that were generated when the creation failed. Once I fixed that everything worked fine.
Thanks
I just found this question when I had a situation where I added some columns to a table, and my edmx file would update just fine; however, the code generation was not triggering properly, so my .cs files were not updating. I right clicked on the Entities.tt file and selected "Run Custom Tool" which runs the text transformations, which fixed it for me.
I ran into this problem a while ago and was able to deal with it by removing the particular table from the model, then doing the "Update model from database" step, selecting that table.
Make sure your 'Model.edmx' file has the name same as 'Model.tt' if not, just rename it the same name with the *.tt file. Then delete entities from designer and import again by 'update model from database'.

How to generate Views using databasefirst and entity framework?

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.

Error 3023 using Entity Framework

Using the Entity Framework, I've modeled a fairly simple database schema with an ever-so-slightly more complex class hierarchy. In two places, I'm using single table inheritance with a single NVARCHAR(20) NOT NULL discriminator column. In one of those two places, it works great, no issues. But in the other place, with an almost identical pattern, I get the following error:
Error 3023: Problem in Mapping Fragments starting at lines 371, 375, 379, 382: Column MediaStream.MediaStreamTypeID has no default value and is not nullable. A column value is required to store entity data.
An Entity with Key (PK) will not round-trip when:
((PK does NOT play Role 'MediaStream' in AssociationSet 'FK_MediaStream_SessionID' OR PK is NOT in 'MediaStream' EntitySet OR Entity is type [SlideLinc.Model].MediaStream) AND (PK plays Role 'MediaStream' in AssociationSet 'FK_MediaStream_SessionID' OR PK is NOT in 'MediaStream' EntitySet OR Entity is type [SlideLinc.Model].MediaStream) AND (PK plays Role 'MediaStream' in AssociationSet 'FK_MediaStream_SessionID' OR PK is in 'MediaStream' EntitySet))
Here's the table definition (not including various indexes, foreign keys, etc.):
CREATE TABLE [dbo].MediaStream(
[MediaStreamID] UNIQUEIDENTIFIER NOT NULL,
[SessionID] UNIQUEIDENTIFIER NOT NULL,
[RtmpUri] nvarchar(250) NOT NULL,
[MediaStreamTypeID] nvarchar(20) NOT NULL,
CONSTRAINT PK_MediaStream PRIMARY KEY CLUSTERED
(
[MediaStreamID] ASC
)
I'm using the MediaStreamtypeID column as the discriminator: if it's set to "video", a VideoMediaStream class should be created, and if it's set to "audio", an AudioMediaStream class should be created.
The relevant portions of the EDMX file look like this:
<EntitySetMapping Name="MediaStream">
<EntityTypeMapping TypeName="IsTypeOf(SlideLinc.Model.MediaStream)">
<MappingFragment StoreEntitySet="MediaStream">
<ScalarProperty Name="RtmpUri" ColumnName="RtmpUri" />
<ScalarProperty Name="MediaStreamID" ColumnName="MediaStreamID" /></MappingFragment></EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(SlideLinc.Model.VideoMediaStream)">
<MappingFragment StoreEntitySet="MediaStream" >
<ScalarProperty Name="MediaStreamID" ColumnName="MediaStreamID" />
<Condition ColumnName="MediaStreamTypeID" Value="video" /></MappingFragment></EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(SlideLinc.Model.AudioMediaStream)">
<MappingFragment StoreEntitySet="MediaStream" >
<ScalarProperty Name="MediaStreamID" ColumnName="MediaStreamID" />
<Condition ColumnName="MediaStreamTypeID" Value="audio" /></MappingFragment></EntityTypeMapping></EntitySetMapping>
<AssociationSetMapping Name="FK_MediaStream_SessionID" TypeName="SlideLinc.Model.FK_MediaStream_SessionID" StoreEntitySet="MediaStream">
<EndProperty Name="MediaStream">
<ScalarProperty Name="MediaStreamID" ColumnName="MediaStreamID" /></EndProperty>
<EndProperty Name="Session">
<ScalarProperty Name="SessionID" ColumnName="SessionID" /></EndProperty></AssociationSetMapping>
So there are multiple things about this error that I don't get:
(1) Why does exactly this same approach work for my other class hierarchy, but not this one? I thought it might be the Entity Designer getting confused, so I deleted this portion of my hierarchy (in the XML), and recreated it, but I'm still getting it. I could try recreating the whole damn thing, but hell, that's a lot of work, and if I'm gonna have to be doing this very often, that doesn't leave a great taste in my mouth about the entity framework.
(2) What is it complaining about in the first place? I don't get how MediaStreamTypeID (which isn't a member of the primary key) has anything to do with the primary key at all, or why the fact that it can't be null is a problem (especially given that this same setup works elsewhere in my model!).
Any thoughts or suggestions?
I had a similar problem, and was able to solve it by setting the "Abstract" property for the base class to "True" and by removing the discriminator column from the base class in the model (either in the *.edmx file or in the designer view within Visual Studio).
I got the exactly same error but maybe with different reason from yours.
In the code below, I mis-copied some codes so 2 of inherited classes (LeveledItem and Team) are of the same "Type".
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new ScrumDbContextInitializer());
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<LeveledItem>()
.Map<LeveledItem>(m => m.Requires("Type").HasValue(typeof(LeveledItem).Name))
.Map<Team>(m => m.Requires("Type").HasValue(typeof(LeveledItem).Name))
.Map<Story>(m => m.Requires("Type").HasValue(typeof(Story).Name))
.Map<Task>(m => m.Requires("Type").HasValue(typeof(Task).Name)) .Map<Sprint>(m => m.Requires("Type").HasValue(typeof(Sprint).Name));
After the second one was changed to "typof(Team).Name", the error was fixed.
I had a similar problem to this, just out of interest, does deleting the .EDMX file and recreating it from scratch solve your problem?
What caused the problem:
Created a set of tables with some 0..* mappings
Generated the Entity Framework class, customised a whole bunch of Navigation properties
Went back to the DB and changed the cardinality of some of the 0..* to 1..* relationships - ie: set some of the FKs to !nullable
Updated the Entity Framework
Recompiled and BOOM I got a compilation error similar to yours
There seems to be an issue where the "Update Model from Database" command doesn't update the changed relationships correctly.
The solution was to open the EDMX file, look for the <Association Name="FK_XXX_XXX"> elements that were generated the first time and change the Multiplicity attribute on the relevant End point from Multiplicity="0..1" to Multiplicity="1"
I encountered this error when I inadvertently mapped 2 classes to the same table via the [Table] attribute (same effect via modelBuilder ToTable())

Entity framework - "Problem in mapping fragments"-error. Help me understand the explanations of this error

Error 3007: Problem in Mapping Fragments starting at lines 186, 205: Non-Primary-Key column(s) [WheelID] are being mapped in both fragments to different conceptual side properties - data inconsistency is possible because the corresponding conceptual side properties can be independently modified.
I found several places on the web describing this error, but I simply don't understand them. (confused smiley goes here)
One
Two
Three
Four
There is something pretty fundamental here, I must be missing. Can you explain it, so that I understand it? Maybe using my real life example below?
Foreign key 1:N Wheels.Id -> Slices.WheelId
I add them to entity framework, and WheelId is not visible in the Slices-entity.
Doing some workaround (deleting the relationship from the db before adding tables to EF - then re-creating it and updating EF) I managed to get the WheelId to stay in Slices, but then I get the error mentioned at the top.
Since Slices.WheelId is an FK, you cannot expose it in your client model, period. There are ways to get the value, though.
var wheelId = someSlice.Wheels.ID;
Update In EF 4 you can do this by using FK Associations instead of independent associations.
Try to remove foreign property column from Entity set using entity model design it will solve your problem
For example
We have two tables one is customer and other one is order, using entity model design we added association between customers and orders when we do this Ado.net entity framework i will add navigation properties to both below tables.
Like
Customer.Orders - Here order is list
Order.Customer
One - Many relation.
So we need to remove property from with name CustomerId[Foreign key column] from Order entity set.
For reference:
http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/2823634f-9dd1-4547-93b5-17bb8a882ac2/
I was able to overcome this problem by the following steps:
right click the designer window
Select 'update model from database'
Select Add AND make sure that the 'Include foreign key columns in the model' checkbox is selected.
click on Finish...
I had set foreign keys up in the database but framework still wasn't pulling them in correctly. So I tried to add the association myself. 
However, when I did this I would get a mapping error. It took me A WHILE but I figured out. What I did was set up the association using the entity toolbox association tool and then you have to double click on the association (1 to many) line and set the primary and foreign key there. Hopefully, this to help others who might have the same problem. I couldn't find the answer anywhere.
I had this problem for quite a different reason, and the message was slightly different; it didn't say "data inconsistency is possible because the corresponding conceptual side properties can be independently modified."
I have a table involved in my model with a binary column where I store image data. I only want this data returned when I need it (performance is a feature), so I split the table using a method similar to this. Later on, I added a property to that table, then updated the model from the database. The wizard added the property to both entity types that refer to the table with the added property. I had to delete it from one of them to solve the error.
I've had this happen because Entity Framework Update wizard mismapped some keys (or did not update?). As a result, some columns were mistakenly labeled as keys, while actual key columns were treated as plain columns.
The solution was to manually open EDMX file, find the entities, and update the keys.
Couldn't get any of the answer to work with EF6. The problem seems to be the framework doesn't import the foreign keys correctly as Associations. My solution was removing foreign keys from the tables, and then manually adding the associations using Entity Framework model, using the following steps: Entity Framework - Add Navigation Property Manually
For LinQ to Entities queries in EF1, my workaround for not having access to the foreign key as a property is with the following code, which does not produce a join query to the associated table:
dbContext.Table1s.FirstOrDefault(c => (int?)c.Table2.Id == null)
i.e, the generated SQL is:
...WHERE ([Extent1].[Table2Id] IS NULL)...
Solution is to allow deleting Rule = Cascade on Sql association.
Same thing as to be done on .edmx model, adding element to
association:
<Association Name="FK_Wheels_Slices">
<End Role="Wheels" Type= "your tipe here" Multiplicity="1">
<OnDelete Action="Cascade" />
</End>
</Association>
I had a table already mapped in EF. I added two more tables which had foreign keys in the previously added table. I then got the 3007 error.
To fix the error I deleted all three tables from the EDMX file, and then re-added them all at once together (via "Update Model from Database..."), instead of in stages.
I checked my Error List window and noticed I had errors in the model. Fixed them and all is well
in my case I solved this error by tick (include foreign key columns in the model)
- update Model from database
- tick (include foreign key columns in the model)
- finish

How to get store type of an entity set

I'm trying to filter entities based on their store types (either table or view).
I have 2 entities in my test project, one's source is a table and the other's source is a view.
<EntitySet Name="Test" EntityType="TestModel.Store.Test" store:Type="Tables" Schema="dbo" />
<EntitySet Name="TestView" EntityType="TestModel.Store.TestView" store:Type="Views" store:Schema="dbo" store:Name="TestView">
The code sample above is taken from model's edmx file's SSDL section.
I think the store:Type information in SSDL is what i need but i couldn't find a way to retrieve that value using entity-framework api.
Any help will be appreciated.
Well you can query the metadata in the SSDL by looking in the SSpace or the StoreItemCollection.
i.e.
var sspaceEntitySets = context.MetadataWorkspace
.GetItems<EntityContainer>(DataSpace.SSpace)
.First().BaseEntitySets.OfType<EntitySet>();
var entitySet = sspaceEntitySets.First();
var tableType = entitySet
.MetadataProperties["http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator:Type"]
.Value.ToString();
Unfortunately this isn't going to help you tie your classes to whether they come from a table or a view. Because the Entities (i.e. the ones you code against in CSpace) rather than the ones that describe the shapes of the table (i.e. SSpace ones) are in CSpace and in order to know whether an Entity comes from a view or table, you would need to be able to get from the CSpace EntitySet to SSpace EntitySet via the Mapping.
Unfortunately the EF doesn't expose public CSSPace (i.e. there is no way to use the API to read the MSL fragment of the EDMX).
So in order to do this you would have to manually reason over the MSL element, probably using LINQ to XML or something.
Hope this helps
Alex