一尘不染

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

sql

我刚开始一个将应用程序从原始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;

这是一些示例数据,显示有些行完全重复(第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

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

是否可以在没有唯一标识符的情况下将视图添加到实体模型?还是有一种简单的方法可以向视图添加唯一的行标识符?该视图只能从中读取,而不能写入。


阅读 178

收藏
2021-03-17

共1个答案

一尘不染

是否可以在没有唯一标识符的情况下将视图添加到实体模型?

如果没有主键,则不会。这将导致这种错误

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

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

如果仅将主键映射到“国家/地区”字段,例如

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; }
}

,即使您的视图在Oracle查询编辑器上产生了以上两行,Entity Framework也会产生以下不正确的输出:

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2010 20.000000

实体框架会认为第二行与第一行是同一对象。

为了保证唯一性,您必须确定使每一行唯一的列。在上面的示例中,必须包含Year,以便主键是唯一的。IE

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; }
}

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

Country     Year TotalSales
Philippines 2010 20.000000
Philippines 2011 40.000000

此处有完整详细信息:http : //www.ienablemuch.com/2011/06/mapping-class-to-database-
view-with.html


然后,对于没有任何列以使行唯一的视图,要确保Entity Framework可以将视图的每一行映射到其自己的对象,最简单的方法是为视图的 主键
创建一个单独的列,这是一个不错的选择就是在每行上创建一个行号列。例如

create view RowNumberedView as

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

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

2021-03-17