Как настроить EF 4.1 для правильного моделирования нестандартных отношений - PullRequest
1 голос
/ 22 июля 2011

У меня есть следующая модель, которая неизменна:

Person 
-------
int Id (PK)
int CompanyId
bool Deleted

Company
-------
int Id (PK)
int DefaultIdentifierId

Identifier
-------
int PersonId (PK)
int DefaultIdentifierId (PK)
string Identifier

Я создал классы для каждой таблицы, но я стараюсь правильно указать сопоставления с базой данных. Мне нужно иметь возможность вернуть идентификатор не удаленного лица с указанием идентификатора компании и идентификатора. В sql это будет соединение между Company и Identifer через DefaultIdentifierId и соединение между Person и Identifier через PersonId, но я не могу правильно указать это.

1 Ответ

0 голосов
/ 22 июля 2011

Проблема в том, что у вас не может быть свойств навигации между Company и Identifier, поскольку ни DefaultIdentifierId в Company, ни DefaultIdentifierId в Identifier не являются первичными ключами. (В Identifier это только часть ключа.) Однако вы можете смоделировать отношения «один ко многим» между Company и Person и между Person и Identifier. Таким образом, вы можете попробовать эти классы моделей:

public class Person
{
    public int Id { get; set; }
    public int CompanyId { get; set; }
    public Company Company { get; set; }
    public bool Deleted { get; set; }
}

public class Company
{
    public int Id { get; set; }
    public int DefaultIdentifierId { get; set; }
}

public class Identifier
{
    [Key, Column(Order = 1)]
    public int PersonId { get; set; }
    [Key, Column(Order = 2)]
    public int DefaultIdentifierId { get; set; }
    public string IdentifierString { get; set; }

    public Person Person { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<Company> Companies { get; set; }
    public DbSet<Identifier> Identifiers { get; set; }
}

Id в имени DefaultIdentifierId из Company вводит в заблуждение. В этой модели это свойство является простым скалярным свойством, а не свойством внешнего ключа, которое принадлежит любому свойству навигации.

Для выполнения требуемого запроса вам нужно будет использовать Join в LINQ, поскольку вы не можете перейти от Company к Identifier через свойства навигации:

int companyId = 1;
string identifierString = "ABC";

List<int> personIds = context.Identifiers
    .Join(context.Companies,
          i => i.DefaultIdentifierId,
          c => c.DefaultIdentifierId,
          (i, c) => new { i, c })
    .Where(a => a.c.Id == companyId 
             && a.i.IdentifierString == identifierString
             && !a.i.Person.Deleted)
    .Select(a => a.i.Person.Id) // or a.i.PersonId should work as well
    .ToList();

Результат не обязательно уникален, но список личностей.

...