使用相同类型的对象访问不同的表(NHibernate、C#)

Access different tables using the same type of object (NHibernate, C#)

我在处理 NHibernate 时遇到了一些问题。我能够解决大多数在互联网上搜索(主要是在 Whosebug 上)的问题,但我无法解决这个问题。

我在同一个 class 创建的数据库中有两个不同的 table。

public class Person
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual int Age { get; set; }
}

table的名字分别是"Person"和"TestTable"。但是当我想在 "TestTable" 中添加一些东西并使用下面的代码时,它仍然会在 "Person" table 中添加我想添加的东西。 有人知道如何解决这个问题吗?

    public bool Add( string entity_name, T product )
    {
        using ( ITransaction transaction = Session.BeginTransaction() )
        {
            Session.Save( entity_name, product );
            transaction.Commit();
        }

        return true;
    }

好的,伙计们,所以我不得不推迟一点我承诺的回应,因为它不会正常工作。经过一整天的努力,现在我有一些有趣的事情要和你分享。

更准确地说,我的问题是:我有一个访问数据库的系统,我希望在我的数据库中拥有:
- 静态 tables
- 动态 tables.

为什么我想要动态 tables?我可以给你们举个例子:如果我想记录每个人在我的应用程序中所做的事情,并且我想以一种即使我的数据库中有很多日志也不会结束的方式来做可扩展(查询中有很多条件,一个 table 中要过滤的数据很多),我必须每个用户日志 一个 table.

Static tables 将是其他的,就像我上面描述的 class。

在 NHibernate 中,没有一种简单的方法可以做到这一点。他们想将一个 class 和一个映射映射到一个 table,仅此而已。如果你想做任何其他事情,那么你必须愚弄图书馆。这几乎就是我最终所做的:

在一个库项目中,我创建了一个静态 table,如下所示:

  public class GenericTableInfo
    {
        public virtual string name { get; set; }
        public virtual int id { get; set; }
    }

在同一个图书馆项目中,我的动态 table 的一个 class(和 xml,但我不会将 XML 添加到该项目中) , 就像这样:

    public class DynamicPeople
{
        public virtual int id { get; set; }
        public virtual string log { get; set; }
}

当我第一次生成要执行的查询时,使用我在上面描述的库的程序集,NHibernate 将创建静态 tables(带有 XML 的那些和 Class) 并且不会创建与我的 DynamicPeople class.

相关的 table

在名为 AddTable() 的服务中,我必须执行以下操作: - 1. 在GenericTableInfo中添加table名称(更准确地说是它的实体名称);

    1. 获取我的 GenericTableInfo 中包含的所有名称(因此,我在数据库中创建的所有动态表);
    1. 像这样创建会话:

    public static ISession AddTable( string TableName, List TableNames, 数据库 db ) {

    if ( !SessionFactories.ContainsKey( db ) )
    {
        SessionFactories.Add( db, null );
    }
    var _cfg = new Configuration();
    _cfg.Configure( System.IO.Path.Combine( DatabaseConfigurationFiles[db] ) );
    // Add table to the database
    File.Move( @"C:\Generic.hbm.xml", @"C:\" + TableName + ".hbm.xml" );
    string aux = File.ReadAllText(@"C:\" + TableName + ".hbm.xml");
    aux = aux.Replace("generic", TableName);
    File.WriteAllText( @"C:\" + TableName + ".hbm.xml", aux );
    _cfg.AddFile(@"C:\" + TableName + ".hbm.xml");
    var update = new SchemaUpdate( _cfg );
    var sb = new StringBuilder();
    TextWriter output = new StringWriter( sb );
    update.Execute( true, true );
    aux = aux.Replace( TableName, "generic" );
    File.WriteAllText( @"C:\" + TableName + ".hbm.xml", aux );
    File.Move( @"C:\" + TableName + ".hbm.xml", @"C:\Generic.hbm.xml" );
    // Add dynamic tables to my mappings list.
    if ( SessionFactories[ db ] == null )
    {
        var configuration = new Configuration();
        configuration.Configure( DatabaseConfigurationFiles[ db ] );
        configuration.AddAssembly( Assembly.GetExecutingAssembly() );
        string filename = @"C:\Generic.hbm.xml";
        string entityname = "generic";
        string a = "";
        for ( int i = 0 ; i < TableNames.Count() ; i++ )
        {
            File.Move( filename, @"C:\" + TableNames[ i ] + ".hbm.xml" );
    
            filename = @"C:\" + TableNames[ i ] + ".hbm.xml";
            a = File.ReadAllText( filename );
    
            a = a.Replace( entityname, TableNames[ i ] );
            entityname = TableNames[ i ];
            File.WriteAllText( filename, a );
            configuration.AddFile( filename );
            configuration.ClassMappings.Last().EntityName = entityname;
            configuration.ClassMappings.Last().Table.Name = entityname;
            configuration.ClassMappings.Last().DiscriminatorValue = entityname;
        }
        File.Move( filename, @"C:\Generic.hbm.xml" );
        filename = @"C:\Generic.hbm.xml";
        a = File.ReadAllText( filename );
        entityname = TableNames.Last();
        a = a.Replace( entityname, "generic" );
        File.WriteAllText( filename, a );
    
        SessionFactories[ db ] = configuration.BuildSessionFactory();                
    }
    else
    {
        DBStub.CloseSession( db );
        return DBStub.OpenSession( db, TableNames );
    }
    return SessionFactories[ db ].OpenSession();
    

    }

(很抱歉第一行和最后一行没有被识别为代码,我是 Whosebug 的菜鸟,它只是不想将这些行识别为代码。:()

修改我的配置通过更改我的 xml 实体名称和我的映射实体名称和 table 名称来手动添加我的映射会欺骗库,所以它不知道它是相同的 xml,因此,不相同的映射。

这样,您可以在使用 NHibernates 函数查询它们时找到您的 table,使用它的实体名称作为键。然后,它们都将能够映射到相同的 class(在此示例中,它们都将映射到 DynamicPeople)。

我没有看到其他人成功地尝试了这个,所以这是我今天对社区的 2 美分。如果有人有任何问题,请不要犹豫。 :)