C# NHibernate SQL创建导致错误

C# NHibernate SQL创建导致错误,c#,nhibernate,C#,Nhibernate,我有两个类,分别是Order和Orderrow。我用NHibernate来加入它 运行NUnit测试查询时,我遇到一个异常: Logica.NHibernate.Tests.NHibernateTest.SelectAllOrdersFromSupplierNamedKnorrTest: NHibernate.ADOException : could not execute query [ SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt

我有两个类,分别是Order和Orderrow。我用NHibernate来加入它

运行NUnit测试查询时,我遇到一个异常:

Logica.NHibernate.Tests.NHibernateTest.SelectAllOrdersFromSupplierNamedKnorrTest:
NHibernate.ADOException : could not execute query
[ SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM Order this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId ]
[SQL: SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM Order this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId]
  ----> System.Data.SqlClient.SqlException : Incorrect syntax near the keyword 'Order'.
在分析NHibernate创建的SQL时,我注意到Order类正在破坏SQL语句,因为Order by是SQL中的一个内部关键字

这是在NHibernate中创建的SQL:

SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM Order this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId
我在SQL Server 2008 Management studio中对其进行了如下更改:

SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM [Order] this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId`
我在表名Order中添加了括号(如:[Order]),它是固定的

但是我如何在NHibernate中修复这个问题?是否有一个映射XML文件指令来完成此操作

(使用VS2008 SP1、SQL Server 2008 SP1、NHibernate 2.0.1 GA)

请参阅“5.3.SQL引用标识符”一节。Yoo基本上需要这个:

<class name="Order" table="`Order`">

我认为,如果在映射文件中使用SQL Server中的引号(“[”和“]”或DB支持的任何引号),hibernate将在生成查询时引用对象名称


(可能会发布您的映射文件,以便我们查看)

在Fluent NHibernate中,添加

.Column("`Order`");

添加到映射以修复此错误。

使用约定时,可以添加以下内容:

public class TableNameConvention
    : IClassConvention, IClassConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IClassInspector> criteria)
    {
        criteria.Expect(x => Check(x));
    }

    private bool Check(IClassInspector x)
    {
        return String.IsNullOrWhiteSpace(x.TableName) || x.TableName.Equals("`{0}`".Args(x.EntityType.Name));
    }

    public void Apply(IClassInstance instance)
    {
        instance.Table("`" + instance.EntityType.Name + "`");
    }
}
public class ColumnNameConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Apply(IPropertyInstance instance)
    {
        instance.Column("`" + instance.Property.Name + "`");
    }

    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(c => Check(c));
    }

    private bool Check(IPropertyInspector inspector)
    {
        //walkaround:
        //this convention causes problems with Components - creates columns like Issue`Id` so we apply it only to entities

        var type = inspector.EntityType;
        if (!(type.IsSubclassOf(typeof (Entity)) || type.IsSubclassOf(typeof (GlossaryEntity))))
        {
            return false;
        }

        return true;
    }
}
公共类TableNameConvention
:IClassConvention,IClassConventionAcceptance
{
公共无效接受(IAcceptanceCriteria标准)
{
期望(x=>检查(x));
}
私人布尔支票(ICX)
{
返回字符串.IsNullOrWhiteSpace(x.TableName)| | x.TableName.Equals(“{0}”).Args(x.EntityType.Name));
}
公共无效应用(IClassInstance实例)
{
表(“`”+instance.EntityType.Name+“`”);
}
}
要解决保留表名和保留列名(例如“From”)的问题,可以使用以下方法:

public class TableNameConvention
    : IClassConvention, IClassConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IClassInspector> criteria)
    {
        criteria.Expect(x => Check(x));
    }

    private bool Check(IClassInspector x)
    {
        return String.IsNullOrWhiteSpace(x.TableName) || x.TableName.Equals("`{0}`".Args(x.EntityType.Name));
    }

    public void Apply(IClassInstance instance)
    {
        instance.Table("`" + instance.EntityType.Name + "`");
    }
}
public class ColumnNameConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Apply(IPropertyInstance instance)
    {
        instance.Column("`" + instance.Property.Name + "`");
    }

    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(c => Check(c));
    }

    private bool Check(IPropertyInspector inspector)
    {
        //walkaround:
        //this convention causes problems with Components - creates columns like Issue`Id` so we apply it only to entities

        var type = inspector.EntityType;
        if (!(type.IsSubclassOf(typeof (Entity)) || type.IsSubclassOf(typeof (GlossaryEntity))))
        {
            return false;
        }

        return true;
    }
}
公共类ColumnNameConvention:IPropertyConvention,IPropertyConventionAcceptance
{
公共无效应用(IPropertyInstance实例)
{
列(“`”+instance.Property.Name+“`”);
}
公共无效接受(IAcceptanceCriteria标准)
{
标准。期望(c=>Check(c));
}
私人楼宇检查(IPropertyInspector检查员)
{
//演练:
//此约定会导致组件出现问题-创建类似Issue`Id`的列,因此我们仅将其应用于实体
变量类型=inspector.EntityType;
if(!(type.IsSubclassOf(typeof(Entity))| | type.IsSubclassOf(typeof(glossarytentity)))
{
返回false;
}
返回true;
}
}

请注意:我知道[和]不是SQL标准,但这些是SQL server使用的默认引号。在NH中,倒勾实际上用于此,请参见Anton的回答。这是独立于数据库的NH语法。@AndyWhite-同意您的说法。我在这里的假设是,如果我使用1000个保留关键字,并且我相信一个接一个地对保留关键字进行编码是很好的,希望你在这一点上同意我的看法。我所做的[按照我对SQL保留关键字编码的要求]——创建了一个实用程序类,一切正常。这是我自己的实用程序类的一个片段,它有两种风格,一种是带有扩展方法的,另一种是不带扩展方法的,我在这里用单个类提供了这两种风格:公共静态类EncodeSqlReservered{公共静态字符串EncodeKeywordWithBraces(字符串关键字ToEncode){return string.Format(“[{0}]”,keywordToEncode);}公共静态字符串EncodeToBraces(此字符串keywordToEncode){return string.Format(“[{0}]”,keywordToEncode);}您添加了错误的字符。您需要一个“backtick”(NHibernate文档中的术语),它位于Tab键的正下方,而不是撇号。这正是我使属性/列“Order”工作所需的。我使用Order属性创建了类,只有在添加此自定义映射后,它才开始工作。