Как смоделировать объект POCO из многоязычной базы данных с Entity Framework 4? - PullRequest
7 голосов
/ 24 декабря 2010

Я строю новый проект с нуля. Я создал базу данных, в которой последовательно применил структуру базы данных, которую я объясняю на коротком понятном примере:

Элемент таблицы -> (Id, Name) -> Содержит общую информацию

Таблица ItemInfo -> (Item_Id, Language, Description) -> Содержит информацию, зависящую от языка.

Id и Item_Id связаны отношением внешнего ключа.

Моя идея состояла в том, чтобы смоделировать его таким образом, чтобы в итоге я использовал только один объект POCO "Item", заполненный через Entity Framework. Этот объект будет содержать только открытые свойства: Id, Name и Description. Язык будет скрыт для кода, использующего этот объект, сам объект должен отвечать за правильное описание в зависимости от глобальной переменной, содержащей язык.

Я пробовал несколько способов сделать это, и у меня всегда возникали проблемы, потому что Entity Framework не допускал такой сценарий. Мне всегда приходилось получать информацию для ВСЕХ языков, а не только для текущего, или использовать 2 разных запроса.

Итак, в конце концов я начал использовать решение, позволяющее шаблону T4 создавать Item и ItemInfo, а затем я вручную добавил код, подобный следующему:

public partial class Item
{
    private ItemInfo _itemInfo = null;
    private ItemInfo itemInfo
    {
        get
        {
            if (_itemInfo == null) _itemInfo = ItemInfoes.Single(p => p.Language == GlobalContext.Language);
            return _itemInfo;
        }
    }
    public Description 
    {
        get { return itemInfo.Description; } 
        set { itemInfo.Description = value;}
    }
}

С помощью этого кода я добавил дополнительные свойства ItemInfo в Item и выбрал правильный язык в соответствии с моими требованиями. Как вы думаете, это хорошее решение? Как бы вы решили эту проблему вместо этого?

Однако, запустив SQL Server Profiler, я вижу, что для заполнения объекта Item используются 2 разных SQL-запроса, один из которых запрашивает таблицу Item, а другой - ItemInfo.

Может ли тот же сценарий быть достигнут с помощью одного запроса, который объединяет две таблицы? (Я боюсь долгосрочного снижения производительности, а также так я бы сделал это без ORM).

Любые предложения будут приветствоваться, у меня есть многолетний опыт программирования, но я новичок в Entity Framework и ORM в целом.

Пожалуйста, помогите.

Ответы [ 3 ]

6 голосов
/ 17 августа 2011

Вы не показываете, как вы выбираете объекты Item, но обычно я не вижу проблемы с извлечением всего в одном запросе.У вас есть несколько вариантов.
Вы можете сделать проекцию (но не на сопоставленную сущность - в этом примере я проецирую на анонимный объект):

context.
Items.
Select(item => new 
               {
                   Id = item.Id,
                   Name = item.Name,
                   Description = item.
                                 ItemInfo.
                                 Where(info => info.Language == YourGlobalLang).
                                 Select(info => info.Description).
                                 FirstOrDefault()
               };

(Это былоотредактировано для использования FirstOrDefault вместо Single - см. обсуждение комментариев с @Craig Stuntz)

Это вернет список всех Items - вы можете добавить предложение Where для фильтрации.

Или вы можете получить его наоборот (начиная с ItemInfo):

ItemInfo itemInfo = context.
                    ItemInfoes.
                    Include(info => info.Item).
                    SingleOrDefault(info => info.Language == YourGlobalLang && 
                                            info.Item.Id == itemIdToFetch);

После этого вы можете получить доступ к самому объекту элемента:

Item item = itemInfo.Item;
1 голос
/ 17 августа 2011

Я бы сказал, что это разумный подход. Кроме того, я бы не стал беспокоиться о проблемах производительности с двумя простыми выборами. Если в будущем это станет проблемой, вы можете изменить ее, например, на представление.

0 голосов
/ 17 августа 2011

Вы можете попытаться добавить предложение where динамически. Или, как было сказано, используйте linq to sql напрямую.

Как добавить предложение where к объектному набору Entity Framework

Добавление предложения where динамически в Entity Framework

...