Может ли EF4.1 Code First одновременно выразить 1-1 и 1-много в одной и той же таблице? - PullRequest
1 голос
/ 25 марта 2011

Проблема высокого уровня: я хотел бы получить быстрый просмотр таблицы, с которой у меня отношение 1-многие.

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

Можно ли сделать что-то подобное с аннотациями?

public class TagEntry
{
    public int TagEntryId { get; set; }

    public int TagId { get; set; }
    public DateTime LogTime { get; set; }
    public string log { get; set; }

    public virtual Tag tag { get; set; }
}

public class Tag
{

    public int TagId { get; set; }
    public TagEntry CurrentTagEntry { get; set; }
    public int TagEntryId { get; set; }

    public string someTagData { get; set; }
    public virtual ICollection<TagEntry> TagEntries { get; set; }
}

Одним из решений было бы просто сохранить целочисленный currentTagEntryId, но в идеале я бы хотел сослаться на Log с нотацией типа tag.CurrentTagEntry.log.

1 Ответ

1 голос
/ 25 марта 2011

К сожалению, это невозможно с помощью картографирования. Ваше CurrentTagEntry отражает отношение один-к-одному между Tag и TagEntry, но в то же время у вас есть отношение один-ко-многим между Tag и TagEntry. Сопоставление один-к-одному требует, чтобы оба объекта совместно использовали первичный ключ =>, чтобы иметь возможность отображать отношения один-к-одному. PK TagEntry должен быть от FK до Tag. Это, очевидно, нарушит отношение один ко многим.

Вы должны сделать это как вспомогательную функцию вместо отображения.

Например, это можно использовать как вспомогательный запрос linq:

var lastLog = (from te in context.TagEntries
               where te.TagId == id
               orderby te.LogTime descending
               select te).FirstOrDefault();

Или это как вспомогательная загрузка:

var entry = context.Entry<Tag>(tag);
if (!entry.Collection(t => t.TagEntries).IsLoaded)
{
    // Selective eager loading
    entry.Collection(t => t.TagEntries)
         .Query()
         .OrderByDescending(te => te.LogTime)
         .Take(1)
         .Load();
}

var tag = tag.TagEntries.FirstOrDefault();
...