实体框架 - 实体只读属性映射到相关列的列 [英] Entity Framework - Entity read-only property mapped to a column of related table
问题描述
我有一个有趣的问题需要解决,但是虽然很常见,但实际框架看起来并不容易实现。有两个表:
I have interesting problem to solve but, although common, it looks like it's not easily achievable with Entity Framework. There are two tables:
Player(Id,TeamId,FirstName,LastName)
Team(Id, Name, IsProfessional)
玩家只能属于一个团队。使用TPT(DB首先),我们有两个类映射到这些表:
Player can belong only to one team. Using TPT (DB first), we have two classes mapped to those tables:
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 on Player实体:
What I would like to achieve is property IsProfessional on Player 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;}
**public bool IsProfessional{get;}** should be read-only
}
是否可以配置映射方式IsProfessional属性可以在linq查询中使用?
Is it possible to configure mapping that way IsProfessional property can be used in linq queries?
var result= db.Players.Where(p=>p.IsProfessional==true);
并且每当玩家实体实现时填充该字段?
and to have that field populated every time Player entity is materialized?
Player pl = db.Players.Where(p=>p.FirstName="Lionel").FirstOrDefault();
if(pl.IsProfessional)
{
//do something...
}
已尝试使用:
- 实体拆分。不可能,因为我想保持团队映射,因为关系不是1:1)
- 将Player实体映射到数据库视图。不喜欢它,因为还有其他关系我需要的玩家实体。我知道可以手动创建它们,但从数据库更新edmx将重置ssdl。
- Entity Splitting. Not possible because I want to keep Team mapping and because relationship is not 1:1)
- Mapping Player entity to a db view. Didn't like it because there are other relationships Player entity has that I need. I know it is possible to create them manually, but updating edmx from database will reset ssdl.
谢谢
解决方案
根据Gert Arnold答案中的第二个选项,适合我需求的解决方案如下: / p>
Based on second option in Gert Arnold answer, solution that fits my needs is as follows:
-
我创建函数
GetIsProfessional
(必须这样做,因为计算字段通常只能从自己的表格中进行)
I create function
GetIsProfessional
(had to do it because computed fields normally can be made only from own table fields)
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)
使用db第一个方法,我jus从数据库更新模型就是这样,我可以查询该字段,并且在Player对象实现时预先填充。
As I'm using db first approach, I just update model from database and that's it, I can query on that field and it's pre populated when Player object is materialized.
推荐答案
这不能用EF完成。有些选项并不完全符合您的要求,但是几乎或多或少地接近:
This can't be done with EF. There are some options that don't do exactly what you want, but get close more or less:
-
创建属性
TeamPlayers
在您的上下文中返回包含该团队的玩家,以便您始终可以执行player.Team.IsProfessional
甚至当上下文已经被放弃时。
Create a property
TeamPlayers
in your context that returns the players with the team included, so that you can always doplayer.Team.IsProfessional
even when the context has already been diposed.
public IQueryable<PLayer> TeamPlayers
{
get { return this.Players.Include("Team"); }
}
在数据库表中创建一个计算字段并映射到它与 DatabaseGeneratedOption.Computed
。
在中创建一个静态属性Player
返回访问
Team.IsProfessional
的表达式(需要包含生活环境或团队):
Create a static property in Player
that returns the expression that accesses Team.IsProfessional
(requires a living context or team included):
public static Expression<Func<PLayer, bool>> IsProfessional
{
get { return p => p.Team.IsProfessional; }
}
...
db.Players.Where( p=> p.FirstName="Lionel").Where(Player.IsProfessional)....
我宁愿计算字段,因为它总是填充,所以你可以在内部和外部的范围内使用它。
I would prefer the calculated field, because it is always populated, so you can use it inside and outside the scope of a context.
这篇关于实体框架 - 实体只读属性映射到相关列的列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!