Сопоставить сущность с таблицей поиска с составным внешним ключом, который частично жестко закодирован - PullRequest
1 голос
/ 07 апреля 2020

Используя EF Core 3.1.2 для базы данных, у нас есть модель, как показано ниже. Это унаследованная база данных, и изменение схемы не является предпочтительным. У нас также есть групповое решение отдавать предпочтение аннотациям данных, а не беглым.

У нас есть много разных таблиц, у которых есть связанные строки в ReferenceDictionary. Связь между этими таблицами и ReferenceDictionary определяется составным ключом (ReferenceDictionary.Category, ReferenceDictionary.Id). Значение Category всегда одинаково для любой данной строки в одной и той же связанной таблице.

Например, во всех случаях FooEntity из FooTable для ReferenceDictionary.Category используется значение 'FooCategory'. Аналогично, все экземпляры BarEntity из BarTable используют значение 'BarCategory' для ReferenceDictionary.Category.

Category для ReferenceDictionary фактически не сохраняется нигде в FooTable или BarTable, однако (нет столбцов базы данных FooEntity.ReferenceDictionaryCategory или BarEntity.ReferenceDictionaryCategory).

Я попробовал решение ниже, используя атрибут [NotMapped] для настройки этого отношения, но я получаю ошибку, что FooEntity.ReferenceDictionaryCategory не столбец в базе данных (а это не так).

Вопрос:

Как настроить отношения EF, чтобы навигационное свойство FooEntity.ReferenceDictionary было успешным сопоставляется с экземпляром ReferenceDictionary с использованием следующего составного сопоставления клавиш?

  • ReferenceDictionary.Category = 'FooCategory'
  • ReferenceDictionary.Id = FooEntity.ReferenceDictionaryId

Текущий код:

public class ReferenceDictionary
{
    [PrimaryKey(Order = 1)]
    public string Category { get; set; }

    [PrimaryKey(Order = 2)]
    public int Id { get; set; }

    ...
}

public class FooEntity
{
    [Key]        
    public int Id { get; set; }

    [NotMapped]
    public string ReferenceDictionaryCategory { get; } = "FooCategory";

    public int ReferenceDictionaryId { get; set; }

    [ForeignKey(nameof(ReferenceDictionaryCategory) + ", " + nameof(ReferenceDictionaryId))]
    public virtual ReferenceDictionary ReferenceDictionary { get; set; }

    ...
}

public class BarEntity
{
    [Key]        
    public int Id { get; set; }

    [NotMapped]
    public string ReferenceDictionaryCategory { get; } = "BarCategory";

    public int ReferenceDictionaryId { get; set; }

    [ForeignKey(nameof(ReferenceDictionaryCategory) + ", " + nameof(ReferenceDictionaryId))]
    public virtual ReferenceDictionary ReferenceDictionary { get; set; }

    ...
}

1 Ответ

1 голос
/ 15 апреля 2020

Когда вы устанавливаете внешний ключ как это

[ForeignKey("ReferenceDictionaryCategory,ReferenceDictionaryId")]
public virtual ReferenceDictionary ReferenceDictionary { get; set; }

и после попытки загрузить данные, как показано ниже,

var test = await _dbcontext.FooEntities.Include(x => x.ReferenceDictionary).ToListAsync();

Это будет преобразовано в sql, как показано ниже,

SELECT  [x].[Id], 
        [x].[ReferenceDictionaryCategory], 
        [x].[ReferenceDictionaryId], 
        [x.ReferenceDictionary].[Category], 
        [x.ReferenceDictionary].[Id]
FROM [FooEntity] AS [x]
LEFT JOIN [ReferenceDictionary] AS [x.ReferenceDictionary] 
ON ([x].[ReferenceDictionaryCategory] = [x.ReferenceDictionary].[Category]) 
    AND ([x].[ReferenceDictionaryId] = [x.ReferenceDictionary].[Id])

Вот почему вы получаете [ReferenceDictionaryCategory] не столбец. Это не дает никакого эффекта, добавляя [NotMapped], потому что это не место для вызова столбца.

Обходной путь, вы можете написать запрос, как показано ниже. (Если вы не хотите добавлять столбец ReferenceDictionaryCategory к FooEntity)

var result = from fe in _dbcontext.FooEntities
             join rd in _dbcontext.ReferenceDictionaries
             on new { Category = "FooCategory", fe.Id } equals new { rd.Category, rd.Id } into data
             from final in data.DefaultIfEmpty()
             select new FooEntity
             {
                 Id = fe.Id,
                 ReferenceDictionaryId = fe.ReferenceDictionaryId,
                 ReferenceDictionary = final
             };

Это сгенерирует sql следующим образом.

SELECT [rd].[Category], [rd].[Id], [fe].[Id] AS [Id0], [fe].[ReferenceDictionaryId]
FROM [FooEntity] AS [fe]
LEFT JOIN [ReferenceDictionary] AS [rd] ON (N'FooCategory' = [rd].[Category]) AND ([fe].[Id] = [rd].[
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...