Свободное владение NHibernate + AutoMappings: загадочный столбец в сгенерированном SQL - PullRequest
2 голосов
/ 03 октября 2010

Я получаю SQL-запрос от NH, и он генерирует несуществующий столбец (таким образом, генерируя ADOException от NH).

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 и creationby_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], потому что я получаю ошибки SQL, используя только User. Соглашение 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. */
}

В моей таблице назначений теперь есть такой столбец.

[CreatedBy_id] INT NULL

И в этом новом столбце есть FK для таблицы User.

Если я закомментирую это свойство, все снова будет работать. SQL возвращается к запросам user_id, именно так, как я ожидал. Есть ли какой-нибудь тип переопределения, который я могу использовать, чтобы предотвратить это?

1 Ответ

1 голос
/ 03 октября 2010

Ну, у меня есть решение, но я не знаю, является ли это лучшим ответом, или есть еще лучшее решение.

Я могу добавить следующее в мой класс 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, и мне не нужно начинать добавлять переопределения.

...