NHibernate 3.0 IQueryable выбор столбца-призрака - PullRequest
3 голосов
/ 08 июня 2011

Я получаю странную ошибку при выполнении того, что кажется простым запросом.

return (from x in session.Query<Contact>()
                .Where(x => x.Id == 10)
               select new ContactIndexViewModel
               {
                   Id = x.Id,
                   Name = x.BasicInfo.FirstName + " " + x.BasicInfo.LastName,
                   Filters = x.Filters
               }).FirstOrDefault();

генерирует следующий SQL

select 
    contact0_.[Id] as col_0_0_, 
    contact0_.[BasicInfoFirstName] as col_1_0_, 
    contact0_.[BasicInfoLastName] as col_2_0_, 
    . as col_3_0_,
    filters1_.[Id] as column1_16_, 
    filters1_.Criteria1 as Criteria2_16_, 
    // .. .more filters1_ fields
    filters1_.ContactId as ContactId16_ 
from 
    [MyServer].[dbo].[Contact] contact0_ 
    inner join [MyServer].[dbo].[Filter] filters1_ 
        on contact0_.[Id]=filters1_.ContactId
where
    contact0_.[Id]=@p0

Обратите внимание, что выбран четвертый столбец . BasicInfo является компонентом, и выбор (в запросе) включает в себя все поля, определенные в ViewModel.

У меня нет других проблем с объектами Contact или Filter в других частях приложения. Контакт -> Фильтр имеет отношение один ко многим.

Есть идеи о том, как отлаживать или что может быть причиной этого?

UPDATE

Если я удалю ссылку на Фильтры в select, проблема исчезнет.

ОБНОВЛЕНИЕ Соответствующие сопоставления

Контакт

public partial class ContactMap : ClassMap<Contact>
{
    /// <summary>Initializes a new instance of the <see cref="ContactMap"/> class.</summary>
    public ContactMap()
    {
        Table("[MyServer].[dbo].[Contact]");
        OptimisticLock.Version();
        DynamicUpdate();
        LazyLoad();

        Id(x=>x.Id)
            .Access.CamelCaseField(Prefix.Underscore)
            .Column("[Id]")
            .GeneratedBy.Identity();
        Version(x=>x.RecordVersion)
            .Access.CamelCaseField(Prefix.Underscore)
            .Column("[RecordVersion]")
                .CustomSqlType("timestamp")
                .Not.Nullable()
            .UnsavedValue("null")
            .CustomType("BinaryBlob")
            .Generated.Always();
        Map(x=>x.Active).Access.CamelCaseField(Prefix.Underscore);
        // other scalar properties
        Component(x0=>x0.BasicInfo, m0=>
        {
            m0.Map(x1=>x1.FirstName).Column("[BasicInfoFirstName]").Access.CamelCaseField(Prefix.Underscore);
            m0.Map(x1=>x1.LastName).Column("[BasicInfoLastName]").Access.CamelCaseField(Prefix.Underscore);
            // other scalar properties
        });

        // other relationships

        HasMany(x=>x.Searches)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.AllDeleteOrphan()
            .Fetch.Select()
            .Inverse()
            .LazyLoad()
            .KeyColumns.Add("ContactId");           
    } 
} 

Поиск

public partial class SearchMap : ClassMap<Search>
{
    public SearchMap()
    {
        Table("[MyServer].[dbo].[Search]");
        OptimisticLock.Version();
        DynamicUpdate();
        LazyLoad();

        Id(x=>x.Id)
            .Access.CamelCaseField(Prefix.Underscore)
            .Column("[Id]")
            .GeneratedBy.Identity();
        Map(x=>x.Controller).Not.Nullable().Access.CamelCaseField(Prefix.Underscore);
        Map(x=>x.Module).Not.Nullable().Access.CamelCaseField(Prefix.Underscore);
        Map(x=>x.Name).Column("[Name]").Not.Nullable().Access.CamelCaseField(Prefix.Underscore);

        References(x=>x.Contact)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.All()
            .Fetch.Select()
            .Columns("ContactId");
        HasMany(x=>x.DataFilters)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.AllDeleteOrphan()
            .Fetch.Select()
            .Inverse()
            .LazyLoad()
            .KeyColumns.Add("SearchId");
    } 
} 

Ответы [ 2 ]

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

Ваше отображение таблицы необычно для меня.

Table("[MyServer].[dbo].[Contact]");

Обычно имя сервера указывается при настройке, схема указывается отдельно, а разделители ("[...]")устанавливается NHibernate.Я бы отобразил это как:

Schema("dbo");
Table("Contact");

Это может вызвать проблемы с синтаксическим анализом, приводящие к нечетному выбору.Если это не так, то я думаю, что это ошибка - NHibernate никогда не должен выдавать select без псевдонима таблицы и имени столбца.

0 голосов
/ 21 июня 2011

Вы сопоставили фильтры с FetchMode.Join?

Между прочим, может быть проще создать ContactIndexViewModel в памяти, с компромиссом, что он выбирает слишком много столбцов из базы данных. С другой стороны, Get не сбрасывает сеанс, что может иметь значение для производительности.

var contact = session.Get<Contact>(10);

return new ContactIndexViewModel
{
     Id = contact.Id,
     Name = contact.BasicInfo.FirstName + " " + contact.BasicInfo.LastName,
     Filters = contact.Filters
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...