gpt4 book ai didi

NHibernate SchemaExport 无法删除表 .... 有时

转载 作者:行者123 更新时间:2023-12-03 18:12:20 25 4
gpt4 key购买 nike

我将 NHibernate 用于我的应用程序的 DAL,尤其是 NHibernate 的 SchemaExport 函数,用于在执行单元测试之前删除/重新创建我的数据库模式。我遇到的问题是,当我运行单元测试并执行 SchemaExport 时,我的一个表无法每两次删除一次。这将向我表明存在某种阻止 SchemaExport 删除我的表的外键问题 - 但我无法弄清楚。我的架构非常简单 - 一个人表、一个地址表和一个 PersonAddress 表来支持两者之间的多对多关系。

public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Address> Addresses {get;set;}

public Person()
{
this.Addresses = new List<Address>();
}

}

public class Address
{
public virtual int Id { get; set; }
public virtual string Street1 { get; set; }
public virtual string Street2 { get; set; }
public virtual string Postcode { get; set; }

}

和我的 NHibernate 映射文件...
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="MyHibernate"
namespace="MyHibernate"
>
<class name="Person" table="Person.Person">
<id name="Id" column="Id">
<generator class="native" ></generator>
</id>
<property name="Name" column="Name" length="50"></property>
<bag name="Addresses" table="[Person].[PersonAddress]" lazy="false" cascade="all">
<key column="PersonId" foreign-key="FK_Person_Person_Id"></key>
<many-to-many class="Address" column="AddressId"></many-to-many>
</bag>
</class>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="MyHibernate"
namespace="MyHibernate"
>
<class name="Address" table="Person.Address">
<id name="Id" column="Id">
<generator class="native" ></generator>
</id>
<property name="Street1" column="Street1" length="50"></property>
<property name="Street2" column="Street2" length="50"></property>
<property name="Postcode" column="Postcode" length="50"></property>
</class>

当我运行 `var cfg = new Configuration();
cfg.Configure();
cfg.AddAssembly(typeof(Person).Assembly);
        new SchemaExport(cfg).Execute(false, true, false, false)

我收到一个 SQL 异常说:

MyHibernate.Tests.GenerateSchemaFixture.Can_Generate_Schema:
NHibernate.HibernateException :数据库中已经有一个名为“Person”的对象。
----> System.Data.SqlClient.SqlException : 数据库中已经有一个名为“Person”的对象。

有任何想法吗?

最佳答案

长期以来,这对我来说一直是一个反复出现的问题。先执行drop或者使用execute方法都没有解决问题(drop方法是执行Execute方法的快捷方式)。

在查看 NHibernate 源代码后,我找到了问题的根源。 NHibernate 使用哈希码在数据库中存储外键名称。然而,哈希码的问题在于它们会随着时间、clr-version 和 appdomain 发生变化。您不能依赖哈希码来实现平等。 (ref: http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx ) 这就是为什么 NHibernate 不能总是删除外键,因此不能删除表。

这是 NHibernate 源代码的快照,用于创建唯一的外键名称:

public string UniqueColumnString(IEnumerable iterator, string referencedEntityName)
{
// NH Different implementation (NH-1339)
int result = 37;
if (referencedEntityName != null)
{
result ^= referencedEntityName.GetHashCode();
}
foreach (object o in iterator)
{
result ^= o.GetHashCode();
}
return (name.GetHashCode().ToString("X") + result.GetHashCode().ToString("X"));
}

所以这个问题不会被NHibernate解决,你必须自己解决。我通过在创建架构之前执行以下方法解决了这个问题。该方法仅从使用 NHibernate 映射的表中删除所有外键:
private static void DropAllForeignKeysFromDatabase()
{
var tableNamesFromMappings = Configuration.ClassMappings.Select(x => x.Table.Name);

var dropAllForeignKeysSql =
@"
DECLARE @cmd nvarchar(1000)
DECLARE @fk_table_name nvarchar(1000)
DECLARE @fk_name nvarchar(1000)

DECLARE cursor_fkeys CURSOR FOR
SELECT OBJECT_NAME(fk.parent_object_id) AS fk_table_name,
fk.name as fk_name
FROM sys.foreign_keys fk JOIN
sys.tables tbl ON tbl.OBJECT_ID = fk.referenced_object_id
WHERE OBJECT_NAME(fk.parent_object_id) in ('" + String.Join("','", tableNamesFromMappings) + @"')

OPEN cursor_fkeys
FETCH NEXT FROM cursor_fkeys
INTO @fk_table_name, @fk_name

WHILE @@FETCH_STATUS=0
BEGIN
SET @cmd = 'ALTER TABLE [' + @fk_table_name + '] DROP CONSTRAINT [' + @fk_name + ']'
exec dbo.sp_executesql @cmd

FETCH NEXT FROM cursor_fkeys
INTO @fk_table_name, @fk_name
END
CLOSE cursor_fkeys
DEALLOCATE cursor_fkeys
;";

using (var connection = SessionFactory.OpenSession().Connection)
{
var command = connection.CreateCommand();
command.CommandText = dropAllForeignKeysSql;
command.ExecuteNonQuery();
}
}

非常适合我。我希望其他人也能使用它。
这是我抓取 sql 脚本以删除所有外键的地方: http://mafudge.mysite.syr.edu/2010/05/07/dropping-all-the-foreign-keys-in-your-sql-server-database/

关于NHibernate SchemaExport 无法删除表 .... 有时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/730725/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com