实体框架 - 实体只读属性映射到相关表的列

Mis*_* N. 6 entity-framework entity-framework-4 ef-database-first

我有一些有趣的问题需要解决,但是虽然很常见,但实际上看起来它并不容易实现.有两个表:

Player(Id,TeamId,FirstName,LastName)
Team(Id, Name, IsProfessional)
Run Code Online (Sandbox Code Playgroud)

玩家只能属于一个团队.使用TPT(DB first),我们有两个映射到这些表的类:

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

我想要实现的是Player实体上的属性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
    }
Run Code Online (Sandbox Code Playgroud)

是否可以配置映射,以便在linq查询中使用IsProfessional属性?

var result= db.Players.Where(p=>p.IsProfessional==true);
Run Code Online (Sandbox Code Playgroud)

并且每次玩家实体实现时都填充该字段?

Player pl = db.Players.Where(p=>p.FirstName="Lionel").FirstOrDefault();
if(pl.IsProfessional)
{
//do something...
}
Run Code Online (Sandbox Code Playgroud)

已经尝试过:

  • 实体分裂.不可能,因为我想保持团队映射,因为关系不是1:1)
  • 将Player实体映射到db视图.不喜欢它,因为玩家实体有我需要的其他关系.我知道可以手动创建它们,但是从数据库更新edmx将重置ssdl.

谢谢

基于Gert Arnold回答的第二个选项,符合我需求的解决方案如下:

  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
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我在Player桌面上创建了计算字段

    ALTER TABLE Players ADD [IsProfessional] AS dbo.GetIsProfessional(TeamId)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 因为我正在使用数据库第一种方法,我只是从数据库更新模型,就是这样,我可以在该字段上查询,并且在实现Player对象时预先填充它.

Ger*_*old 8

这不能用EF完成.有些选项并不能完全符合您的要求,但可以或多或少地接近:

  1. TeamPlayers在您的上下文中创建一个属性,该属性返回包含团队的玩家,这样player.Team.IsProfessional即使已经使用了上下文,您也可以随时执行此操作.

    public IQueryable<Player> TeamPlayers
    {
        get { return this.Players.Include("Team"); }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在数据库表中创建一个计算字段并映射到它DatabaseGeneratedOption.Computed.

  3. 创建一个静态属性Player,返回访问的表达式Team.IsProfessional(需要包含生命上下文或团队):

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

我更喜欢计算字段,因为它总是填充,因此您可以在上下文范围内外使用它.