NHibernate 3.0 IQueryable选择鬼列

时间:2011-06-08 17:35:48

标签: linq nhibernate

运行看似简单的查询时,我收到一个奇怪的错误。

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是一个组件,select(在查询中)包括ViewModel中定义的所有字段。

我没有在应用程序的其他部分中使用Contact或Filter对象的任何其他问题。联系 - &gt;过滤器具有一对多的关系。

有关如何调试或可能导致此问题的任何想法?

更新

如果删除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 :(得分:0)

您是否使用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
};

答案 1 :(得分:0)

您对该表的映射对我来说并不常见。

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

通常在配置期间提供服务器名称,模式单独说明,分隔符(“[...]”)由NHibernate设置。我会将其映射为:

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

这可能导致解析问题导致奇数选择。如果不是这样,那么我认为这是一个错误 - NHibernate不应该在没有表别名和列名的情况下发出select。