使用没有主键的视图与实体

Mik*_*e B 22 sql oracle entity

我刚刚开始将一个应用程序从原始ADO.NET和嵌入式SQL转换为Entity.我遇到了应用程序使用的其中一个视图的问题.视图没有主键,也没有唯一标识行的列(或列组合).这是选择创建视图:

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;
Run Code Online (Sandbox Code Playgroud)

这里有一些示例数据显示有些行完全重复(第3行和第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 
Run Code Online (Sandbox Code Playgroud)

insuredid是aip.slbtransinsured表的pk,rsn是aip.slbtransinsurer和aip.slblinecodes的pk.

是否可以在没有唯一标识符的情况下向Entity模型添加视图?或者是否有一种简单的方法可以向视图添加唯一的行标识符?视图只读取,从不写入.

Mic*_*uen 33

是否可以在没有唯一标识符的情况下向Entity模型添加视图?

如果没有主键,没有.这将导致这种错误:

在模型生成期间检测到一个或多个验证错误:

System.Data.Edm.EdmEntityType :: EntityType'SalesOnEachCountry'没有定义键.定义此EntityType的键.System.Data.Edm.EdmEntitySet:EntityType:EntitySet SalesOnEachCountryList基于未定义键的SalesOnEachCountry类型.

如果没有唯一标识符,是的,尽管它具有非期望的输出.具有相同标识符的记录将引用相同的对象,这称为标识映射模式

例如,即使您的视图生成以下两行:

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2011 40.000000
Run Code Online (Sandbox Code Playgroud)

如果您只是在国家/地区字段上映射主键,例如

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; }
}
Run Code Online (Sandbox Code Playgroud)

,即使您的视图在Oracle查询编辑器上生成上述两行,Entity Framework也会生成以下错误输出:

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2010 20.000000
Run Code Online (Sandbox Code Playgroud)

实体框架将认为第二行与第一行是同一个对象.

为了保证唯一性,您必须确定使每行唯一的列.在上面的示例中,必须包含Year,因此主键是唯一的.即

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; }
}
Run Code Online (Sandbox Code Playgroud)

使主键与上述属性类似,Entity Framework可以正确地将每个视图的行映射到它们自己的对象.因此,实体框架现在可以显示与视图完全相同的行.

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2011 40.000000
Run Code Online (Sandbox Code Playgroud)

详情请见:http://www.ienablemuch.com/2011/06/mapping-class-to-database-view-with.html


然后,关于没有任何列以使行唯一的视图,保证实体框架可以将每个视图的行映射到它们自己的对象的最简单方法是为视图的主键创建单独的列,这是一个很好的候选者就是在每一行上创建一个行号列.例如

create view RowNumberedView as

select 
    row_number() over(order by <columns of your view sorting>) as RN
    , *
from your_existing_view
Run Code Online (Sandbox Code Playgroud)

然后[Key]在你的RN属性上分配属性class RowNumberedView


小智 18

扩展了Michael Buen的答案:我发现使用ISNULL()将行号添加到视图中将允许实体框架拉入视图并自动创建必要的EntitySet数据.

create view RowNumberedView as

select 
    ISNULL(ROW_NUMBER() OVER (ORDER BY <column>), 0) AS RN
    , *
from your_existing_view
Run Code Online (Sandbox Code Playgroud)