6

私は解決すべき面白い問題がありますが、一般的ですがEntity Frameworkでは容易に実現できないようです。 2つのテーブルがあります。Entity Framework - 関連テーブルの列にマップされたエンティティの読み取り専用プロパティ

Player(Id,TeamId,FirstName,LastName) 
Team(Id, Name, IsProfessional) 

プレーヤーは1つのチームにのみ所属できます。使用TPT(DB最初)、我々は2つのクラスがこれらのテーブルにマップされています:私が達成したい何

public class Player 
{ 
    public int Id{get;set;} 
    public int TeamId{get;set;} 
    public string FirstName{get; set;} 
    public string LastName{get; set;} 
    public Team Team{get;set;} 
} 

public class Team 
{ 
    public int Id{get; set;} 
    public string Name{get;set;} 
    public bool IsProfessional{get;set;} 
    public IEnumerable<Player> Players{get;} 
} 

プレーヤーエンティティのプロパティIsProfessionalです:

public class Player 
    { 
     public int Id{get;set;} 
     public int TeamId{get;set;} 
     public string FirstName{get; set;} 
     public string LastName{get; set;} 
     public Team Team{get;set;} 
     **public bool IsProfessional{get;}** should be read-only 
    } 

は、それが可能なマッピングを設定することですものlinqクエリでIsProfessionalプロパティを使用できますか?

var result= db.Players.Where(p=>p.IsProfessional==true); 

このフィールドにPlayerエンティティがマテリアライズされるたびにそのフィールドが設定されますか?

  • エンティティ分割
    Player pl = db.Players.Where(p=>p.FirstName="Lionel").FirstOrDefault(); 
    if(pl.IsProfessional) 
    { 
    //do something... 
    } 
    

    はすでにしてみました。チームマッピングを維持したい、関係が1:1でないために不可能)
  • dbビューへのプレーヤーエンティティのマッピング。他の関係があるので好きではなかったPlayerのエンティティには必要なものがあります。手動で作成することは可能ですが、edmxをデータベースから更新するとssdlがリセットされます。

ゲルト・アーノルドの答えでは第二の選択肢に基づきおかげ

ソリューション

を、次のように私のニーズに合ったソリューションです:

  1. 私は機能GetIsProfessionalは(しなければならなかった作成計算されたフィールドは通常、自分のテーブルフィールドからしか作成できないため)

    CREATE FUNCTION [dbo].[GetIsProfessional](@teamId as INT) 
    RETURNS bit 
    
    BEGIN 
    
    DECLARE @isProfi AS bit 
    
    SELECT @isProfi = IsProfessional 
    FROM Teams 
    WHERE Id = @teamId 
    
    RETURN @isProfi 
    
    END 
    
  2. 私はデシベル最初のアプローチを使用しています、私は、データベースからモデルを更新し、それはそれだと、私はその場で問い合わせることができますPlayerテーブル

    ALTER TABLE Players ADD [IsProfessional] AS dbo.GetIsProfessional(TeamId) 
    
  3. に、計算フィールドを作成し、それは事前に人口ですPlayerオブジェクトがマテリアライズされたとき。

+0

だから 'Player.IsProfessional'は' Player.Team.IsProfessional'と同じ結果を与えるはずですか? EFは現在、単純なデータベースフィールドにマップされていないプロパティをサポートしていません。申し訳ありませんが、おそらく誰かが良い選択肢で回答します。 – hvd

+0

それはPlayer.IsProfessionalを読むことを除いて、私が必要とするものです。私が自分で見つけられるすべての選択肢は、本当に素晴らしいものではありません。 –

答えて

8

これはEFで行うことはできません。正確に何をしたいけど、得ることはありませんいくつかのオプションがあります近い多かれ少なかれ:

  1. あなたは常に行うことができるように、チームと選手が含ま返すあなたのコンテキスト内のプロパティTeamPlayersを作成します。コンテクストが既にダイペースされている場合でさえ、player.Team.IsProfessionalである。

    public IQueryable<PLayer> TeamPlayers 
    { 
        get { return this.Players.Include("Team"); } 
    } 
    
  2. データベーステーブルに計算フィールドを作成し、DatabaseGeneratedOption.Computedでそれにマップされます。

  3. (生活状況やチームが含まが必要です)Team.IsProfessionalにアクセス表現を返すPlayerに静的プロパティを作成します。

    public static Expression<Func<PLayer, bool>> IsProfessional 
    { 
        get { return p => p.Team.IsProfessional; } 
    } 
    ... 
    db.Players.Where(p=> p.FirstName="Lionel").Where(Player.IsProfessional).... 
    

それは常に人口であるので、私は、計算フィールドを好むだろうしたがって、コンテキストの範囲の内側と外側で使用することができます。私はEF5's Model Firstアプローチでこの属性を使用して、私はDbContext/DbSet上とを照会

// Mapped part of entity 
public class Player 
{ 
    public int Id { get; set; } 
    public int TeamId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public Team Team { get; set; } 
} 

// Unmapped part of entity 
using System.ComponentModel.DataAnnotations.Schema; 
... 
public partial class Player 
{ 
    [NotMapped()] 
    public bool IsProfessional { get { /* ... IsProfessional calculation logic comes here ... */ } } 
} 

+0

素晴らしい!計算フィールドは私のニーズに最も合っています:1)計算フィールドで照会することができます.2)他のプレーヤーのプロパティでデータが取り込まれています。どうもありがとう! –

0

Playerを拡張してTeamからプルするプロパティを持つ場合はどうなりますか?もちろん

public partial class Player 
{ 
    public int Id{get;set;} 
    public int TeamId{get;set;} 
    public string FirstName{get; set;} 
    public string LastName{get; set;} 
    public Team Team{get;set;} 

    public bool IsProfessional{ get { return Team.IsProfessional; } } 
} 

、あなたはEDMXを再生心配している場合、あなたはそれが部分的に行うことができます:

public partial class Player 
{ 
    public bool IsProfessional{ get { return Team.IsProfessional; } } 
} 
+0

はい、このようにPlayer.IsProfessionalはlinqクエリでは使用できません。また、プロパティPlayer.IsProfessionalにアクセスすると、dbから1つのブール値を取得するためにsqlクエリが実行されます。そのブール値が他のすべてのPlayerプロパティと同時に満たされている場合は、私は好きです。 –

0

あなたはこれらのようなIsProfessionalプロパティのマッピングを防ぐためにSystem.ComponentModel.DataAnnotations.Schema.NotMappedAttributeを使用することができますObjectContext/ObjectQuery例外なく。 (100%テスト済み)

+0

このプロパティは、このエンティティから作成したデータソースには表示されません。 –

+0

私は通常、ObjectDataSourceを使用して、自分のエンティティクラスのすべてのパブリックプロパティを表示します。 私は、EntityDataSourceは、.edmxファイルのスキーマ宣言のために生成されたエンティティのマップされたプロパティを読み込んだと思います。 – Perseus

+0

これは機能しますか?上記のLinqの問題はどうですか? – Worthy7

関連する問題