我有一些有趣的问题需要解决,但是,虽然常见,但看起来它并不容易通过Entity Framework实现。有两个表:
Player(Id,TeamId,FirstName,LastName)
Team(Id, Name, IsProfessional)
玩家只能属于一个团队。使用TPT(DB优先),我们有两个映射到这些表的类:
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;}
}
我想要实现的是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
}
是否可以配置映射,以便在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...
}
已经尝试过:
由于
解决方案
根据Gert Arnold的第二个选项回答,符合我需求的解决方案如下:
我创建了函数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
我在Player
表
ALTER TABLE Players ADD [IsProfessional] AS dbo.GetIsProfessional(TeamId)
由于我正在使用数据库第一种方法,我只是从数据库更新模型,就是这样,我可以在该字段上查询,并且在实现Player对象时预先填充它。
答案 0 :(得分:8)
使用EF无法做到这一点。有些选项并不能完全符合您的要求,但可以或多或少地接近:
在您的上下文中创建一个属性TeamPlayers
,返回包含该团队的玩家,这样即使已经使用了上下文,您也可以player.Team.IsProfessional
。
public IQueryable<Player> TeamPlayers
{
get { return this.Players.Include("Team"); }
}
在数据库表格中创建一个计算字段,并使用DatabaseGeneratedOption.Computed
映射到该字段。
在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)....
我更喜欢计算字段,因为它总是被填充,因此您可以在上下文范围内外使用它。
答案 1 :(得分:0)
如果您将Player扩展为拥有从团队中获取的属性,该怎么办?
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; } }
}
答案 2 :(得分:0)
您可以使用System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute
来阻止 IsProfessional
属性的映射,如下所示:
// 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 ... */ } }
}
我在 EF5's Model First
方法中使用了此属性,并查询了 DbContext/DbSet
和 ObjectContext/ObjectQuery
,没有任何例外。 (100%测试)