NHibernate Исключение при создании SessionFactory, если имя столбца совпадает для свойства ассоциации - PullRequest
1 голос
/ 20 апреля 2020

У меня есть таблицы Master и Detail. Имя столбца первичного ключа в обеих таблицах одинаково: Id.
При создании фабрики сеансов я получаю следующее исключение:

NHibernate.MappingException: Unable to build the insert statement for class ........Detail1Entity: a failure occured when adding the Id of the class ---> System.ArgumentException: The column 'Id' has already been added in this SQL builder
Parameter name: columnName
   at NHibernate.SqlCommand.SqlInsertBuilder.AddColumnWithValueOrType(String columnName, Object valueOrType)
   at NHibernate.SqlCommand.SqlInsertBuilder.AddColumns(String[] columnNames, Boolean[] insertable, IType propertyType)
   at NHibernate.Persister.Entity.AbstractEntityPersister.GenerateInsertString(Boolean identityInsert, Boolean[] includeProperty, Int32 j)
   --- End of inner exception stack trace ---
   at NHibernate.Persister.Entity.AbstractEntityPersister.GenerateInsertString(Boolean identityInsert, Boolean[] includeProperty, Int32 j)
   at NHibernate.Persister.Entity.AbstractEntityPersister.GenerateInsertString(Boolean[] includeProperty, Int32 j)
   at NHibernate.Persister.Entity.AbstractEntityPersister.PostInstantiate()
   at NHibernate.Persister.Entity.SingleTableEntityPersister.PostInstantiate()
   at NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
   at NHibernate.Cfg.Configuration.BuildSessionFactory()
   at ...........

У меня есть следующие таблицы:

CREATE Table MasterTable1
(
[Id] [INT] IDENTITY (1,1) NOT NULL CONSTRAINT MasterTable1PK PRIMARY KEY,
[MasterData] [VARCHAR] (100)
)

CREATE Table DetailTable1
(
[Id] [INT] IDENTITY (1,1) NOT NULL CONSTRAINT DetailTable1PK PRIMARY KEY,
[MasterId] [INT] NOT NULL CONSTRAINT DetailTable1_MasterTable1_FK FOREIGN KEY REFERENCES MasterTable(MasterId),
[DetailData] [VARCHAR] (100)
)

Ниже приведены определения сущностей:

public class Master1Entity
{
    public virtual int Id { get; set; }
    public virtual string MasterData { get; set; }
}

public class Detail1Entity
{
    public virtual int Id { get; set; }
    public virtual string DetailData { get; set; }

    public virtual Master1Entity Master1 { get; set; }
}

Ниже приведены сопоставления:

internal class Master1Map : ClassMapping<Master1Entity>
{
    public Master1Map()
    {
        Table("MasterTable1");

        Id(x => x.Id, im =>
        {
            im.Column("Id");
            im.Generator(Generators.Identity);
        });
        Property(x => x.MasterData);
    }
}

internal class Detail1Map : ClassMapping<Detail1Entity>
{
    public Detail1Map()
    {
        Table("DetailTable1");

        Id(x => x.Id, im =>
        {
            im.Column("Id");
            im.Generator(Generators.Identity);
        });
        Property(x => x.DetailData);

        ManyToOne(x => x.Master1, map => { map.Column("Id"); });
    }
}

Как объяснено здесь , я знаю, что если я переименую [MasterTable1].[Id] [MasterTable1].[MasterId] и соответственно измените сущности и отображения, это будет хорошо работать.

Но я не могу изменить базовую базу данных; это устаревшая база данных, которую я должен взять на себя.

Кроме того, это отношения «многие к одному». Один мастер будет иметь несколько записей сведений.

Есть ли способ выполнить эту работу без изменения имени столбца в базе данных?

1 Ответ

3 голосов
/ 21 апреля 2020

Не путайте отображение коллекции (ожидает столбец из таблицы ассоциации) с отображением объекта (ожидает столбец из таблицы владельца). ManyToOne является отображением сущности и ожидает столбец из таблицы owner . В вашем случае таблица владельца для Master1 равна DetailTable1, а столбец, который необходимо сопоставить, равен MasterId:

internal class Detail1Map : ClassMapping<Detail1Entity>
{
...
 ManyToOne(x => x.Master1, map => { map.Column("MasterId"); });
...