Есть ли что-то аналогичное в NHibernate в отношении свойства навигации Entity Framework? - PullRequest
3 голосов
/ 09 апреля 2011

Есть ли что-то аналогичное в NHibernate в отношении свойства навигации Entity Framework?Например, вместо:

s.Save(new Product { Category = s.Get<Category>("FD"), Name = "Pizza" });

Я хотел бы написать:

s.Save(new Product { CategoryId = "FD", Name = "Pizza" });

Могу ли я сообщить NHibernate, чтобы он не использовал свойство категории продукта в качестве механизма для сохранения категории продукта?Я хочу использовать CategoryId вместо этого (читай: я не хочу использовать DTO).Похоже, что Entity Framework способна полностью избежать шаблонов DTO, в то же время предлагая все преимущества ORM (можно избежать объединений с использованием свойств навигации).Я хочу, чтобы EF предлагал лучшее из обоих миров (экономный механизм для сохранения объектов, т.е. не нужно извлекать объект свойства) и механизм навигации для запросов материала

Пример из EF: http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-code-first-walkthrough.aspx

public class Category
{
    public virtual string CategoryId { get; set; }
    public virtual string Name { get; set; }

    public virtual IList<Product> Products { get; set; }
}

public class Product
{
    public virtual int ProductId { get; set; }
    public virtual string Name { get; set; }
    public virtual string CategoryId { get; set; }

    public virtual Category Category { get; set; }
}

[ОБНОВЛЕНИЕ]

Что касается ответа Джеймса, я пытался увидеть действия NHibernate в SQL Server Profiler.

// this act didn't hit the Category table from the database
var c = s.Load<Category>("FD"); 
// neither this hit the Category table from the database
var px = new Product { Category = c, Name = "Pizza" }; 
// this too, neither hit the Category table from the database
s.Save(px); 

Только при фактическом доступе к категорииобъект, который NHibernate попадет в базу данных

Console.WriteLine("{0} {1}", c.CategoryId, c.Name);

1 Ответ

7 голосов
/ 09 апреля 2011

Если я понимаю ваш вопрос, вы хотите сохранить продукт с категорией, не обращаясь к базе данных, чтобы загрузить объект категории. NHibernate абсолютно поддерживает это, и у вас почти есть правильный код. Вот как вы это делаете в NHibernate:

s.Save(new Product { Category = s.Load<Category>("FD"), Name = "Pizza" });

Это не попадет в базу данных для извлечения фактической категории, а просто сохранит продукт с правильным Category.Id. Обратите внимание, что вам не нужно (и я бы порекомендовал избавиться от Product.CategoryId).

Теперь, почему это работает с session.Load (), но не с session.Get () ... С session.Get () NHibernate должен возвращать объект или нуль. В .NET объект не может заменить себя на NULL после факта. Поэтому NHibernate вынужден перейти в базу данных (или кэш L1), чтобы убедиться, что категория «FD» действительно существует. Если он существует, он возвращает объект. Если нет, он должен вернуть ноль.

Давайте посмотрим на session.Load (). Если объект отсутствует в базе данных, он генерирует исключение. Так что NHibernate может вернуть прокси-объект из session.Load () и задержать фактическое попадание в базу данных. Когда вы на самом деле получаете доступ к объекту, NHibernate проверит базу данных и может вызвать исключение в этот момент, если объект не существует. В этом случае мы сохраняем продукт в базе данных. Все, что нужно NHibernate - это ПК категории, который есть в прокси. Таким образом, он не должен запрашивать базу данных для объекта категории. NHibernate никогда не нуждается в гидратации фактического объекта Category для удовлетворения запроса на сохранение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...