Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a view with no primary key with Entity

Tags:

sql

oracle

entity

I just started on a project converting an application from raw ADO.NET and embedded SQL to Entity. I ran in to a problem with one of the views used by the application. The view has no primary key and no column (or combination of columns) that uniquely identifies a row. Here is the select the view is created with:

SELECT     filingmonth,     CEIL(filingmonth / 3),     licnum,     filingyear,     DECODE(GROUPING(insurername), '1', '- All Insured -', insurername),     insurername,     policylinecode,     linedescription,     SUM(NVL(grosspremium, 0)),     SUM(DECODE(taxexempt, 1, grosspremium, 0)),     TRUNC(       CASE         WHEN           (             b.rsn IS NOT NULL             OR A.zeroreport = 1           )           AND b.datereceived IS NULL             THEN A.datereceived         ELSE b.datereceived       END),     SUM(aip.iscompanyadmitted(b.naiccocode, b.naicalienid)),     A.insuredid   FROM     aip.slbtransinsured A   LEFT OUTER JOIN aip.slbtransinsurer b   ON     A.insuredid = b.insuredid   LEFT OUTER JOIN aip.slblinecodes C   ON     b.policylinecode = C.linecode   WHERE     A.submitted = 1   AND A.entryincomplete = 0   GROUP BY     licnum,     filingmonth,     filingyear,     TRUNC(       CASE         WHEN           (             b.rsn IS NOT NULL             OR A.zeroreport = 1           )           AND b.datereceived IS NULL             THEN A.datereceived         ELSE b.datereceived       END),     ROLLUP(insurername, aip.iscompanyadmitted(b.naiccocode, b.naicalienid),     policylinecode, linedescription), A.insuredid; 

And here is some sample data showing that there are some rows that are completely duplicated (rows 3 and 4):

FILINGMONTH CEIL(FILINGMONTH/3) LICNUM FILINGYEAR DECODE(GROUPING(INSURERNAME),'1','-ALLINSURED-',INSURERNAME)                                         INSURERNAME                                                                                          POLICYLINECODE LINEDESCRIPTION                                                                                                                                                                                          SUM(NVL(GROSSPREMIUM,0)) SUM(DECODE(TAXEXEMPT,1,GROSSPREMIUM,0)) TRUNC(CASEWHEN(B.RSNISNOTNULLORA.ZEROREPORT=1)ANDB.DATERECEIVEDISNULLTHENA.DATERECEIVEDELSEB.DATERECEIVEDEND) SUM(AIP.ISCOMPANYADMITTED(B.NAICCOCODE,B.NAICALIENID)) INSUREDID        6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            17             OTHER LIABILITY                                                                                                                                                                                                            721.25                                       0 18-JUL-07                                                                                                                                                          0        81        6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            17                                                                                                                                                                                                                                        721.25                                       0 18-JUL-07                                                                                                                                                          0        81        6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                                                                                                                                                                                                                                                                      721.25                                       0 18-JUL-07                                                                                                                                                          0        81        6                   2   8150       2007 SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                            SAVERS PROPERTY AND CASUALTY INSURANCE CO                                                                                                                                                                                                                                                                                                      721.25                                       0 18-JUL-07                                                                                                                                                          0        81  

insuredid is the pk for the aip.slbtransinsured table, rsn is the pk for aip.slbtransinsurer and aip.slblinecodes.

Is it at all possible to add a view to the Entity model without a unique identifier? Or is there an easy way to add a unique row identifier to the view? The view is only read from, never written to.

like image 237
Mike B Avatar asked Jul 06 '12 22:07

Mike B


People also ask

Can you create a view without primary key?

There is, however, a way to get a view added as a "read only entity" sans primary key if you use database-first Entity Framework. You even get a neat error when you add a view without an obvious key that says EF is forcing your entity to be a keyless read-only entity.

Can we use Entity Framework without primary key?

The Entity framework will not support to have a table without primary key, but we can overcome this issue by accessing the table with additional column via a view and marking the new column as Primary in entity framework. Entity Framework requires primary keys for entities.

What happens if no primary key?

Every table can have (but does not have to have) a primary key. The column or columns defined as the primary key ensure uniqueness in the table; no two rows can have the same key. The primary key of one table may also help to identify records in other tables, and be part of the second table's primary key.

Can we create table without primary key in Entity Framework Code First?

Popular Answer There is a great difference between what EF can do with a database, and what is possible with a database. Most databases allow for a table to be without a primary key.


1 Answers

Is it at all possible to add a view to the Entity model without a unique identifier?

If without a primary key, no. That will result to this kind of error:

One or more validation errors were detected during model generation:

System.Data.Edm.EdmEntityType: : EntityType 'SalesOnEachCountry' has no key defined. Define the key for this EntityType. System.Data.Edm.EdmEntitySet: EntityType: The EntitySet SalesOnEachCountryList is based on type SalesOnEachCountry that has no keys defined.

If without a unique identifier, yes, albeit it has a non-desirable output. Records with same identifier would reference the same object, this is called Identity Map Pattern

An example, even if your view produces these two rows:

Country     Year TotalSales Philippines 2010 20.000000 Philippines 2011 40.000000 

If you will just map the primary key on Country field only, e.g.

public class SalesOnEachCountry {             [Key]     public int CountryId { get; set; }     public string CountryName { get; set; }             public int OrYear { get; set; }     public long SalesCount { get; set; }     public decimal TotalSales { get; set; } } 

, even your view produces the above two rows on your Oracle query editor, Entity Framework produces this incorrect output:

Country     Year TotalSales Philippines 2010 20.000000 Philippines 2010 20.000000 

Entity Framework will take it that the second row is same object as first row.

To guarantee uniqueness, you must identify what columns that makes each row unique. In the above example, Year must be included so the primary key is unique. i.e.

public class SalesOnEachCountry {             [Key, Column(Order=0)] public int CountryId { get; set; }     public string CountryName { get; set; }     [Key, Column(Order=1)] public int OrYear { get; set; }      public long SalesCount { get; set; }           public decimal TotalSales { get; set; } } 

Making your primary key similar to the attributes above, Entity Framework can correctly map your each view's row to their own objects. Hence, Entity Framework can now display exactly the same rows your view have.

Country     Year TotalSales Philippines 2010 20.000000 Philippines 2011 40.000000 

Full details here: http://www.ienablemuch.com/2011/06/mapping-class-to-database-view-with.html


Then regarding your views which don't have any columns to make a row unique, the easiest way to guarantee Entity Framework can map each of your view's row to their own objects is to create a separate column for your view's primary key, a good candidate is to just create a row number column on each row. e.g.

create view RowNumberedView as  select      row_number() over(order by <columns of your view sorting>) as RN     , * from your_existing_view 

Then assign the [Key] attribute on RN property of your class RowNumberedView

like image 116
Michael Buen Avatar answered Oct 08 '22 12:10

Michael Buen