[entity-framework] Entity Framework and SQL Server View

For several reasons that I don't have the liberty to talk about, we are defining a view on our Sql Server 2005 database like so:

CREATE VIEW [dbo].[MeterProvingStatisticsPoint]
AS
SELECT
    CAST(0 AS BIGINT) AS 'RowNumber',
    CAST(0 AS BIGINT) AS 'ProverTicketId',
    CAST(0 AS INT) AS 'ReportNumber',
    GETDATE() AS 'CompletedDateTime',
    CAST(1.1 AS float) AS 'MeterFactor',
    CAST(1.1 AS float) AS 'Density',
    CAST(1.1 AS float) AS 'FlowRate',
    CAST(1.1 AS float) AS 'Average',
    CAST(1.1 AS float) AS 'StandardDeviation',
    CAST(1.1 AS float) AS 'MeanPlus2XStandardDeviation',
    CAST(1.1 AS float) AS 'MeanMinus2XStandardDeviation'
WHERE 0 = 1

The idea is that the Entity Framework will create an entity based on this query, which it does, but it generates it with an error that states the following:

Warning 6002: The table/view 'Keystone_Local.dbo.MeterProvingStatisticsPoint' does not have a primary key defined. The key has been inferred and the definition was created as a read-only table/view.

And it decides that the CompletedDateTime field will be this entity primary key.

We are using EdmGen to generate the model. Is there a way not to have the entity framework include any field of this view as a primary key?

The answer is


If you do not want to mess with what should be the primary key, I recommend:

  1. Incorporate ROW_NUMBER into your selection
  2. Set it as primary key
  3. Set all other columns/members as non-primary in the model

Agree with @Tillito, however in most cases it will foul SQL optimizer and it will not use right indexes.

It may be obvious for somebody, but I burned hours solving performance issues using Tillito solution. Lets say you have the table:

 Create table OrderDetail
    (  
       Id int primary key,
       CustomerId int references Customer(Id),
       Amount decimal default(0)
    );
 Create index ix_customer on OrderDetail(CustomerId);

and your view is something like this

 Create view CustomerView
    As
      Select 
          IsNull(CustomerId, -1) as CustomerId, -- forcing EF to use it as key
          Sum(Amount) as Amount
      From OrderDetail
      Group by CustomerId

Sql optimizer will not use index ix_customer and it will perform table scan on primary index, but if instead of:

Group by CustomerId

you use

Group by IsNull(CustomerId, -1)

it will make MS SQL (at least 2008) include right index into plan.

If


To get a view I had to only show one primary key column I created a second view that pointed to the first and used NULLIF to make the types nullable. This worked for me to make the EF think there was just a single primary key in the view.

Not sure if this will help you though since I don't believe the EF will accept an entity with NO primary key.


I was able to resolve this using the designer.

  1. Open the Model Browser.
  2. Find the view in the diagram.
  3. Right click on the primary key, and make sure "Entity Key" is checked.
  4. Multi-select all the non-primary keys. Use Ctrl or Shift keys.
  5. In the Properties window (press F4 if needed to see it), change the "Entity Key" drop-down to False.
  6. Save changes.
  7. Close Visual Studio and re-open it. I am using Visual Studio 2013 with EF 6 and I had to do this to get the warnings to go away.

I did not have to change my view to use the ISNULL, NULLIF, or COALESCE workarounds. If you update your model from the database, the warnings will re-appear, but will go away if you close and re-open VS. The changes you made in the designer will be preserved and not affected by the refresh.


Due to the above mentioned problems, I prefer table value functions.

If you have this:

CREATE VIEW [dbo].[MyView] AS SELECT A, B FROM dbo.Something

create this:

CREATE FUNCTION MyFunction() RETURNS TABLE AS RETURN (SELECT * FROM [dbo].[MyView])

Then you simply import the function rather than the view.


The current Entity Framework EDM generator will create a composite key from all non-nullable fields in your view. In order to gain control over this, you will need to modify the view and underlying table columns setting the columns to nullable when you do not want them to be part of the primary key. The opposite is also true, as I encountered, the EDM generated key was causing data-duplication issues, so I had to define a nullable column as non-nullable to force the composite key in the EDM to include that column.


This method works well for me. I use ISNULL() for the primary key field, and COALESCE() if the field should not be the primary key, but should also have a non-nullable value. This example yields ID field with a non-nullable primary key. The other fields are not keys, and have (None) as their Nullable attribute.

SELECT      
ISNULL(P.ID, - 1) AS ID,  
COALESCE (P.PurchaseAgent, U.[User Nickname]) AS PurchaseAgent,  
COALESCE (P.PurchaseAuthority, 0) AS PurchaseAuthority,  
COALESCE (P.AgencyCode, '') AS AgencyCode,  
COALESCE (P.UserID, U.ID) AS UserID,  
COALESCE (P.AssignPOs, 'false') AS AssignPOs,  
COALESCE (P.AuthString, '') AS AuthString,  
COALESCE (P.AssignVendors, 'false') AS AssignVendors 
FROM Users AS U  
INNER JOIN Users AS AU ON U.Login = AU.UserName  
LEFT OUTER JOIN PurchaseAgents AS P ON U.ID = P.UserID

if you really don't have a primary key, you can spoof one by using ROW_NUMBER to generate a pseudo-key that is ignored by your code. For example:

SELECT
ROW_NUMBER() OVER(ORDER BY A,B) AS Id,
A, B
FROM SOMETABLE


Examples related to entity-framework

Entity Framework Core: A second operation started on this context before a previous operation completed EF Core add-migration Build Failed Entity Framework Core add unique constraint code-first 'No database provider has been configured for this DbContext' on SignInManager.PasswordSignInAsync The instance of entity type cannot be tracked because another instance of this type with the same key is already being tracked Auto-increment on partial primary key with Entity Framework Core Working with SQL views in Entity Framework Core How can I make my string property nullable? Lazy Loading vs Eager Loading How to add/update child entities when updating a parent entity in EF

Examples related to sql-server-2005

Add a row number to result set of a SQL query SQL Server : Transpose rows to columns Select info from table where row has max date How to query for Xml values and attributes from table in SQL Server? How to restore SQL Server 2014 backup in SQL Server 2008 SQL Server 2005 Using CHARINDEX() To split a string Is it necessary to use # for creating temp tables in SQL server? SQL Query to find the last day of the month JDBC connection to MSSQL server in windows authentication mode How to convert the system date format to dd/mm/yy in SQL Server 2008 R2?

Examples related to .net-3.5

Get first element from a dictionary redistributable offline .NET Framework 3.5 installer for Windows 8 How to read an entire file to a string using C#? HTTP Error 500.22 - Internal Server Error (An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode.) Change the Textbox height? How to get current date in 'YYYY-MM-DD' format in ASP.NET? C# Numeric Only TextBox Control Will the IE9 WebBrowser Control Support all of IE9's features, including SVG? Use LINQ to get items in one List<>, that are not in another List<> Get Absolute URL from Relative path (refactored method)

Examples related to primary-key

Violation of PRIMARY KEY constraint. Cannot insert duplicate key in object What is Hash and Range Primary Key? Can I use VARCHAR as the PRIMARY KEY? Can a foreign key refer to a primary key in the same table? UUID max character length MySQL duplicate entry error even though there is no duplicate entry Creating composite primary key in SQL Server What are the best practices for using a GUID as a primary key, specifically regarding performance? Add primary key to existing table Create view with primary key?

Examples related to sql-view

Working with SQL views in Entity Framework Core Create view with primary key? Computed / calculated / virtual / derived columns in PostgreSQL SQL Views - no variables? Entity Framework and SQL Server View