Свободное использование NHibernate + AutoMappings: загадочный столбец в сгенерированном SQL

Я получаю 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 и 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>();
                               });            
} 

Моя настраиваемая конфигурация говорит, что нужно отображать только публичные автосвойства. Это сделано для того, чтобы я мог добавлять другие вычисляемые свойства к объектам моего домена. Переопределение пользовательской карты гарантирует, что имя таблицы - [User], потому что я получал ошибки SQL, используя только User. Соглашение Custom HasMany устанавливает каскадное удаление-все-удаление-сирота, поскольку все имеет много взаимосвязей.

Изменить № 2

Это становится еще лучше. Это итератор столбца после создания объекта конфигурации, но перед созданием объекта фабрики сеанса.

перед фабрикой сеанса

Видеть? В списке сопоставленных столбцов нет createdby_id столбца. Это итератор столбца после создания объекта фабрики сеанса.

фабрика после сеанса

А теперь есть столбец createdby_id. Я действительно потерялся.

Изменить 3

Хорошо, я думаю, что сейчас кое-что понял.

На прошлой неделе я получил новое требование от моего клиента. Это требование заключалось в том, что они хотели знать, кто создал задание. Итак, у него есть следующее новое свойство.

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

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

[CreatedBy_id] INT NULL

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

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


person Jarrett Meyer    schedule 03.10.2010    source источник
comment
Вы используете AutoMapping или ClassMaps? Можете ли вы опубликовать свой звонок в Fluently.Configure?   -  person Yogesh    schedule 03.10.2010
comment
Вы можете показать нам свои полные объекты? Суффикс _id указывает, что это отношение внешнего ключа, которое было сопоставлено, поэтому где-то в вашем домене должно быть свойство или класс CreatedBy; автоматизатор работает, отражая свойства и классы в ваших сборках, он не может просто создавать вещи.   -  person James Gregory    schedule 03.10.2010
comment
И, пожалуйста, разместите свой CustomHasManyConvention & UserMapOverride.   -  person Yogesh    schedule 03.10.2010


Ответы (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, и мне не нужно начинать переопределения.

person Jarrett Meyer    schedule 03.10.2010