流畅的NHibernate + AutoMappings:生成SQL中的神秘列

时间:2010-10-03 04:11:41

标签: fluent-nhibernate automapping

我从NH获取SQL查询,并且它正在生成一个不存在的列(从而从NH生成ADOException)。

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的Role类映射。它在字典中有4个项目:id,user_id,roledescription和createdby_id。所以查询是基于配置的合法,但我无法根据类找出配置。

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

编辑#1

这是我的Fluently.Configure声明

_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>();
                               });            
} 

我的自定义配置说只映射公共autoproperties。这样我就可以将其他计算属性添加到我的域实体中。用户映射覆盖确保表名为[User],因为我仅使用User收到SQL错误。 Custom HasMany约定为所有人设置级联all-delete-orphan有很多关系。

编辑#2

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

before session factory

请参阅?映射列列表中没有createdby_id列。这是创建会话工厂对象后的列迭代器。

after session factory

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

编辑3

好吧,我想我现在正在做点什么。

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

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

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

[CreatedBy_id] INT NULL

此新列上的User表有一个FK。

如果我注释掉这个属性,一切都会再次起作用。 SQL可以追溯到user_id的查询,正如我预期的那样。我可以使用某种类型的覆盖来防止这种情况发生吗?

1 个答案:

答案 0 :(得分:1)

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

我可以将以下内容添加到我的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");
  }
}

我希望有人告诉我,我的AutoMapping做错了,而且我不需要开始抛弃覆盖。