使用SQLite的nHibernate支持外键

时间:2014-12-12 17:35:08

标签: c# sqlite unit-testing nhibernate automated-tests

nHibernate似乎不支持SQLite的外键。默认情况下,SQLite中不支持外键,但可以通过运行PRAGMA foreign_keys = ON来启用。但我不知道在我的nHibernate代码中如何或在何处执行此操作。

有关如何让nHibernate在SQLite中使用外键的任何想法?我找到了一个旧的解决方法,但没有用(Does SQLite coupled with NHibernate support referential integrity / foreign keys?)。

这是我的代码。映射是使用hbm xml文件完成的,但这不重要。返回的错误是" SQL逻辑错误或缺少数据库附近"约束":语法错误"。

namespace ConsoleApp
{
    public class Employee
    {
        public virtual int Id { get; set; }
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
        public virtual string Email { get; set; }
        public virtual int DepartmentId { get; set; }
        public virtual Department Department { get; set; }
    }

    public class Department
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual List<Employee> Employees { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var cfg = new Configuration();
            cfg.DataBaseIntegration(x =>
            {
                x.ConnectionString = "data source=:memory:";
                x.Driver<SQLite20Driver>();
                x.Dialect<MsSql2012Dialect>();
                x.ConnectionReleaseMode = ConnectionReleaseMode.OnClose;

            });
            cfg.AddAssembly(Assembly.GetExecutingAssembly());

            var sessionFactory = cfg.BuildSessionFactory();
            var session = sessionFactory.OpenSession();

            new SchemaExport(cfg).Execute(true, true, false, session.Connection, null);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你得到&#34; SQL逻辑错误或丢失数据库的原因\ r \ nnene \&#34;约束\&#34;:语法错误&#34;是因为你设置了错误的方言。

您正在使用MsSql2012方言,因此NHibernate将创建SQL语句,认为数据库支持某些功能,但由于它是不同的数据库,因此它不支持它们。

没有编译指示,因为MsSQL没有编译指示,所以请改用SQLiteDialect:

cfg.DataBaseIntegration(x =>
{
  x.ConnectionString = "data source=:memory:";
  x.Driver<SQLite20Driver>();
  x.Dialect<SQLiteDialect>();
  x.ConnectionReleaseMode = ConnectionReleaseMode.OnClose;
});

Documentation

  

您应始终将dialect属性设置为正确   您的数据库的NHibernate.Dialect.Dialect子类。

     

的SQLite
  NHibernate.Dialect.SQLiteDialect
  将driver_class设置为适用于.NET 2.0的System.Data.SQLite提供程序的NHibernate.Driver.SQLite20Driver。

MsSQLDialect的SchemaExport SQL命令:

if exists (select 1 from sys.objects where object_id = OBJECT_ID(N'[FK20E4895FB0DFE40D]') AND parent_object_id = OBJECT_ID('Employee')) alter table Employee  drop constraint FK20E4895FB0DFE40D
if exists (select * from dbo.sysobjects where id = object_id(N'Employee') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table Employee
if exists (select * from dbo.sysobjects where id = object_id(N'Department') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table Department

create table Employee (
    Id INT not null,
    FirstName NVARCHAR(255) null,
    LastName NVARCHAR(255) null,
    Email NVARCHAR(255) null,
    DepartmentId INT null,
    primary key (Id)
)

create table Department (
    Id INT not null,
    Name NVARCHAR(255) null,
    primary key (Id)
)

alter table Employee
    add constraint FK20E4895FB0DFE40D
    foreign key (DepartmentId)
    references Department

这里会失败,因为SQLite不支持alter table add constraint语法(这里是语法错误消息)。

SQLiteDialect的SchemaExport SQL命令:

PRAGMA foreign_keys = OFF

drop table if exists Employee

drop table if exists Department

PRAGMA foreign_keys = ON

create table Employee (
   Id INT not null,
   FirstName TEXT,
   LastName TEXT,
   Email TEXT,
   DepartmentId INT,
   primary key (Id),
   constraint FK20E4895FB0DFE40D foreign key (DepartmentId) references Department
)

create table Department (
   Id INT not null,
   Name TEXT,
   primary key (Id)
)

删除时pragma关闭,然后再次重新启用。