将外键映射到标量属性

时间:2016-12-06 09:29:58

标签: c# .net sql-server entity-framework

我有2个表:DataAdditionalData。他们的关系是1到1-0(任何Data可以有0或1 AdditionalData)。

对于主要上下文,我有类:

class Data
{
    public long Id {get;set;} // PK
    public string Name {get;set;}
    public AdditionalData AdditionalData {get;set;} // can be null
}

class AdditionalData
{
    public long Id {get;set;} // PK
    public string AdditionalName {get;set;}
}

这很好用。

对于我需要知道的另一个背景,Data是否AdditionalData

class ExtendedData
{
    public long Id {get;set;} //PK
    public string Name {get;set;}
    public bool HasAdditionalData {get;set;}
}

我可以将其映射到视图:

SELECT 
     d.*
    ,IIF(ad.Id IS NULL, 0, 1) AS HasAdditionalData
FROM Data AS d
LEFT OUTER JOIN AdditionalData AS ad ON d.Id = ad.Id

但我想知道:

我可以将ExtendedData类映射到没有其他视图的表吗?

2 个答案:

答案 0 :(得分:1)

如果您只是使用ExtendedData作为投影结果,那么下面的查询可能就是您要查找的内容:

var result = ctx.Data.Select(d => new ExtendedData {Id = d.Id, Name = d.Name, HasAdditionalData = d.ApprovalStatus != null);

问题是你的PK正在扮演FK的双重职责,你是否将AdditionalData的FK定义为另一个字段,可能为AdditionalDataId,然后检查是否存在{{1}将是微不足道的;只检查AdditionalData是否为空,您的性能也会提高。

答案 1 :(得分:1)

您可以避免使用DefiningQuery构造创建数据库视图。 DefiningQuery提供与数据库视图相同的功能,但它在模型中定义,而不是在数据库本身中定义。

您无法使用Visual Studio Model Designer创建DefiningQuery,但您应手动编辑edmx文件。首先将EntityTypeEntitySet定义添加到SSDL层:

<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="TestDataModel.Store" Provider="System.Data.SqlClient" ProviderManifestToken="2012" Alias="Self" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">

  <EntityType Name="ExtendedData">
    <Key>
      <PropertyRef Name="Id" />
    </Key>
    <Property Name="Id" Type="bigint" Nullable="false" StoreGeneratedPattern="Identity" />
    <Property Name="Name" Type="nvarchar(max)" Nullable="false" />
    <Property Name="HasAdditionalData" Type="bit" Nullable="false" />
  </EntityType>

  <EntityContainer Name="TestDataModelStoreContainer">
    <EntitySet Name="ExtendedData" EntityType="Self.ExtendedData" store:Type="Views" store:Schema="dbo" store:Name="ExtendedData">
      <DefiningQuery>
        SELECT d.Id, d.Name, CAST(IIF(ad.Id IS NULL, 0, 1) AS BIT) AS HasAdditionalData
        FROM Data AS d
        LEFT OUTER JOIN AdditionalData AS ad ON d.Id = ad.Id
      </DefiningQuery>
    </EntitySet>
  </EntityContainer>

</Schema></edmx:StorageModels>

请注意,您的查看查询是在DefiningQuery元素下指定的,稍作修改。

然后您应该将ExtendedData实体添加到CSDL。这可以通过进一步手动编辑edmx或使用Model Designer来完成。这里最后看起来如何:

<!-- CSDL content -->
<edmx:ConceptualModels>
  <Schema Namespace="TestDataModel" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
    <EntityContainer Name="TestDataEntities2" annotation:LazyLoadingEnabled="true">
      <EntitySet Name="ExtendedDatas" EntityType="TestDataModel.ExtendedData" />
    </EntityContainer>
    <EntityType Name="ExtendedData">
      <Key>
        <PropertyRef Name="Id" />
      </Key>
      <Property Name="Id" Type="Int64" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
      <Property Name="Name" Type="String" Nullable="false" />
      <Property Name="HasAdditionalData" Type="Boolean" Nullable="false" />
    </EntityType>
  </Schema>
</edmx:ConceptualModels>

然后你应该添加CSDL-SSDL映射,再次手动编辑edmx或通过表映射:

<!-- C-S mapping content -->
<edmx:Mappings>
  <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
    <EntityContainerMapping StorageEntityContainer="TestDataModelStoreContainer" CdmEntityContainer="TestDataEntities2">
      <EntitySetMapping Name="ExtendedDatas">
        <EntityTypeMapping TypeName="IsTypeOf(TestDataModel.ExtendedData)">
          <MappingFragment StoreEntitySet="ExtendedData">
            <ScalarProperty Name="HasAdditionalData" ColumnName="HasAdditionalData" />
            <ScalarProperty Name="Name" ColumnName="Name" />
            <ScalarProperty Name="Id" ColumnName="Id" />
          </MappingFragment>
        </EntityTypeMapping>
      </EntitySetMapping>
    </EntityContainerMapping>
  </Mapping>
</edmx:Mappings>

注意:如果从数据库更新模型,则edmx的SSDL部分中的任何手动更改都将丢失。