У меня есть интересная проблема, которую нужно решить, но, хотя она и распространена, похоже, что ее нелегко решить с помощью 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;}
}
Чего я хотел бы добиться, так это свойства IsProfessional для объекта Player:
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?
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)
- Сопоставление объекта Player с представлением базы данных. Мне это не понравилось, потому что у объекта Player есть другие отношения, которые мне нужны. Я знаю, что их можно создать вручную, но обновление edmx из базы данных приведет к сбросу ssdl.
Спасибо
Решение
Основываясь на втором варианте ответа Герта Арнольда, решение, которое соответствует моим потребностям, выглядит следующим образом:
Создаю функцию
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)
Поскольку я использую подход db first, я просто обновляю модель из базы данных, и все, я могу запросить это поле, и оно предварительно заполняется при материализации объекта Player.
Player.IsProfessional
должен давать тот же результат, что иPlayer.Team.IsProfessional
? EF в настоящее время не поддерживает свойства, которые не сопоставляются с простым полем базы данных, извините, но, возможно, кто-то ответит с хорошей альтернативой. - person   schedule 09.10.2012