代码之家  ›  专栏  ›  技术社区  ›  Jarrett Meyer

Fluent NHibernate+自动应用:生成的SQL中的神秘列

  •  2
  • Jarrett Meyer  · 技术社区  · 14 年前

    我从NH获取了一个SQL查询,它生成了一个不存在的列(因此从NH生成了一个AdoException)。

    select roles0_u.createdby_id as createdby4_1_uu,
    角色0.id为id1,
    角色ID为ID18_0_u,
    角色描述为角色描述
    角色0用户ID为用户3用户18用户0_
    来自[角色]角色0_
    Roles0_u.CreatedBy_id=在哪里创建?
    < /代码> 
    
    

    我的问题是,我无法确定createdBy列的来源。这是我的课程结构。

    公共抽象类域实体 { 公共虚拟int id_get;set; } 公共类用户:DomainEntity { /*你所期待的一切*/ 公共虚拟IList<角色>角色获取;私有集; } 公共类角色:DomainEntity { 公共虚拟用户用户get;set; 公共虚拟字符串roledescription_get;set; } < /代码>

    在应用程序启动时,我可以检查配置,并且可以看到角色类映射的columniterator字典中有4个项目:id、user_id、roledescription和createdby_id。因此查询是基于配置的合法查询,但我无法根据类计算出配置。

    是的,我已经清除了我的ASP.NET DLL缓存,删除了bin和obj目录,以及我能想到的任何其他类似的目录。

    编辑1

    这是我的流利配置语句

    _configuration=fluently.configure())
    .database(mssqlconfiguration.mssql2008.connectionString(_connectionString))。
    .mappings(m=>m.automappings.add(getPersistenceModel())
    .buildconfiguration();
    < /代码> 
    
    

    这是我对getPersistenceModel()的调用

    private static autopersistenceModel getPersistenceModel())
    {
    var配置=new customAutomappingConfiguration();
    返回automap.assemblyof<user>(配置)
    .ignorebase(typeof(域实体))
    .useOverridesFromAssemblyof<UserMapOverride>()
    .conventions.setup(c=>
    {
    c.添加<customHasManyConvention>();
    (});
    }
    < /代码> 
    
    

    我的自定义配置表示只映射公共自动属性。这样我就可以将其他计算属性添加到我的域实体中。用户映射覆盖确保表名为[user],因为我使用justuser获得了SQL错误。自定义has many约定集cascade all delete orphan for all具有多个关系。

    编辑2

    这会变得更好。这是在创建配置对象之后,但在创建会话工厂对象之前的列迭代器。

    在映射列列表中没有createdBy_id=>code>column。这是创建会话工厂对象后的列迭代器。

    现在有了一个createdBy_idcolumn。我现在真的迷路了。

    编辑3

    好吧,我想我现在有点想法了。

    上周我接到客户的新要求。这一要求是他们想知道谁创造了一个任务。所以它有一个新的属性,如下所示。

    公共类分配:域实体{ *** 公共虚拟用户createdby get;set; *** } < /代码>

    在我的作业表中,它现在有一个这样的列。

    [createdby_id]int空
    < /代码> 
    
    

    在这个新的列上有一个用户表的fk。

    如果我对这个房产置评,一切都会重新开始。SQL返回到按user_id>进行查询,这正是我期望的方式。是否有某种类型的覆盖可以用来防止这种情况发生?

    SELECT roles0_.CreatedBy_id as CreatedBy4_1_, 
           roles0_.Id as Id1_, 
           roles0_.Id as Id18_0_, 
           roles0_.RoleDescription as RoleDesc2_18_0_, 
           roles0_.User_id as User3_18_0_ 
    FROM [Role] roles0_ 
    WHERE roles0_.CreatedBy_id=?
    

    我的问题是我不知道CreatedBy列来自。这是我的班级结构。

    public abstract class DomainEntity
    {
        public virtual int Id { get; set; }
    }
    public class User : DomainEntity
    {
        /* all the regular stuff you'd expect */
        public virtual IList<Role> Roles { get; private set; }
    }
    public class Role : DomainEntity
    {
        public virtual User User { get; set; }
        public virtual string RoleDescription { get; set; }
    }
    

    在应用程序启动时,我可以检查配置,并且可以看到ColumnIterator用于角色类映射。字典中有4个条目:id、user_id、roledescription和createdby_id,所以查询是合法的,基于配置,但我不能根据类来确定配置。

    是的,我已经清除了我的ASP.NET DLL缓存,删除了bin和obj目录,以及其他我能想到的东西。

    编辑第1页

    这是我的流利配置语句

    _configuration = Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2008.ConnectionString(_connectionString))
        .Mappings(m => m.AutoMappings.Add(GetPersistenceModel()))
        .BuildConfiguration();
    

    这是我的电话GetPersistenceModel()

    private static AutoPersistenceModel GetPersistenceModel()
    {
        var configuration = new CustomAutomappingConfiguration();
        return AutoMap.AssemblyOf<User>(configuration)
            .IgnoreBase(typeof(DomainEntity))
            .UseOverridesFromAssemblyOf<UserMapOverride>()
            .Conventions.Setup(c =>
                                   {
                                      c.Add<CustomHasManyConvention>();
                                   });            
    } 
    

    我的自定义配置表示只映射公共自动属性。这样我就可以将其他计算属性添加到我的域实体中。用户映射重写确保表名为[User],因为我使用User. 自定义has many约定集cascade all delete orphan for all有许多关系。

    编辑第2页

    这会变得更好。这是在创建配置对象之后,但在创建会话工厂对象之前的列迭代器。

    before session factory

    看到了吗?不createdby_id映射列列表中的列。这是创建会话工厂对象后的列迭代器。

    after session factory

    现在有一个创建目录列。我现在真的迷路了。

    编辑3

    好吧,我想我现在有点事了。

    上周我接到客户的新要求。这一要求是他们想知道谁创造了一个任务。所以它有一个新的属性,如下所示。

    public class Assignment : DomainEntity {
      /* etc. */
      public virtual User CreatedBy { get; set; }
      /* etc. */
    }
    

    在我的作业表中,它现在有一个这样的列。

    [CreatedBy_id] INT NULL
    

    在这个新列的用户表中有一个fk。

    如果我对这个房产置评,一切都会重新开始。SQL返回到查询方式user_id正是我所期望的那样。是否有某种类型的覆盖可以用来防止这种情况发生?

    1 回复  |  直到 14 年前
        1
  •  1
  •   Jarrett Meyer    14 年前

    嗯,我有一个解决方案,但我不知道这是最好的答案,还是有更好的解决方案。

    我可以将以下内容添加到我的usermapoverride类中

    public class UserMapOverride : IAutoMappingOverride<User> {
      public void Override(Automapping<User> mapping) {
        // Ensure that the string "User" is properly SQL-escaped. Without this line,
        // SQL queries are breaking.
        mapping.Table("[User]");
    
        // Force the FK to use the correct column.
        mapping.HasMany(x => x.Roles).KeyColumn("User_id");
      }
    }
    

    我希望有人告诉我,我的自动应用出了问题,我不需要开始抛出覆盖。