2016-12-06 3 views
1

У меня есть 2 стола: Data и AdditionalData. Их отношение составляет от 1 до 1-0 (любой Data может иметь 0 или 1 AdditionalData).Map иностранный ключ для скалярного имущества

Для основного контекста у меня есть классы:

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

Это прекрасно работает.

В другом контексте я просто нужно знать, имеет ли DataAdditionalData или нет:

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 с таблицами без дополнительного вида?

+0

@GertArnold no, во втором контексте Я слушал 'AdditionalData' для редактирования – Backs

ответ

1

Запрос как один ниже может быть то, что вы ищете, если вы нормально только с помощью ExtendedData в результате проекции:

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

Проблема в том, что ваш ПК играет двойная пошлина как FK также, если бы вы определили FK для AdditionalData как другое поле, допустимое значение AdditionalDataId, то проверка наличия AdditionalData была бы тривиальной; просто проверьте, нет ли AdditionalDataId, и вы также получите лучшую производительность.

+0

, представьте, что объект' AdditionalData' тяжел (около 1 мб), поэтому очень странно загружать его из БД, просто чтобы проверить его значение null или нет. – Backs

+0

@Backs Проверка FK (свойство AdditionalDataId) не загружает объект. Ленивая загрузка не запускается путем простого доступа к свойству FK id. – Klinger

+0

О, я вижу, что вы имеете в виду. да, это может сработать, если у меня есть дополнительный столбец «AdditionalDataId» с уникальными значениями. Это немного сложная схема. Но возможно, да – Backs

1

Вы можете избежать создания представления базы данных с помощью конструкции DefiningQuery. DefiningQuery предоставляет те же функции, что и представление базы данных, но определен в вашей модели, а не в самой базе данных.

Вы не можете создать DefiningQuery с Visual Studio Model Designer, хотя вы должны вручную отредактировать свой файл edmx. В первую добавить EntityType и EntitySet определений слоя 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 элемента с небольшими изменениями.

Затем вы должны добавить объекту CSDL ExtendedData. Это можно сделать с дальнейшим ручным редактированием 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 или через таблицу Mapping:

<!-- 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> 

Будьте осторожны: Любые изменения вручную в SSDL части вашего edmx будет потерян, если вы обновите свою модель из базы данных.

+0

Интересное решение, когда у вас есть edmx-файл – Backs

Смежные вопросы