Свободный выпуск Nhibernate «многие ко многим» - PullRequest
0 голосов
/ 15 декабря 2010

У меня есть три таблицы:

  1. Person (Id, FirstName)
  2. Organization (Id, Name)
  3. PersonOrganization (PersonId, OrganizationId, Details) много-to-many table

Когда я впервые сопоставил это с помощью Fluent NHibernate, у меня не было столбца сведений в таблице PersonOrganization и сопоставил его с помощью HasManyToMany в PersonMap и OrganizationMap (не нужно создавать PersonOrganizationдоменный объект или карта).Я мог бы написать следующий код:

Organization org = new Organization { Name = "org" };
People people = new People { FirstName = "firstname", Organization = org };

peopleRepository.Add(people);          // ISession.Save(people)
unitOfWork.Commit();                   // ITransaction.Commit()

NHhibernate с радостью зафиксировал данные во всех трех таблицах.

Проблема возникает, когда я добавил столбец сведений в таблицу PersonOrganization.После некоторых исследований выясняется, что теперь мне нужно создать новый объект домена PersonOrganization, отобразить и настроить отношение HasMany как для Person, так и для Organization.Моя обновленная модель и карты ниже:

public class People
{
    public People()
    {
        LinkToOrganization = new List<PeopleOrganization>();
    }

    public virtual int Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual IList<PeopleOrganization> LinkToOrganization { get; set; }
}

public class Organization
{
    public Organization()
    {
        LinkToPeople = new List<PeopleOrganization>();
    }

    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<PeopleOrganization> LinkToPeople { get; set; }
}

public class PeopleOrganization
{
    public virtual People People { get; set; }
    public virtual Organization Organization { get; set; }
    public virtual string Details { get; set; }
}

public class PeopleMap : ClassMap<People>
{
    public PeopleMap()
    {
        Id(p => p.Id);
        Map(p => p.FirstName).Length(100);

        HasMany(x => x.LinkToOrganization)
            .Table("PeopleOrganization")
            .KeyColumn("PeopleId")
            .AsBag()
            .Inverse();
    }
}

public class OrganizationMap : ClassMap<Organization>
{
    public OrganizationMap()
    {
        Id(p => p.Id);
        Map(p => p.Name).Length(50);

        HasMany(x => x.LinkToPeople)
            .Table("PeopleOrganization")
            .KeyColumn("OrganizationId")
            .AsBag()
            .Inverse();
    }
}

public class PeopleOrganizationMap : ClassMap<PeopleOrganization>
{
    public PeopleOrganizationMap()
    {
        CompositeId()
            .KeyReference(p => p.People, "PeopleId")
            .KeyReference(p => p.Organization, "OrganizationId");

        Map(p => p.Details).Length(100);
    }
}

Теперь мне нужно написать следующий код:

People people = new People { FirstName = "firstname" };
Organization org = new Organization { Name = "org" };
PeopleOrganization po = new PeopleOrganization { People = people, Organization = org, Details = "details" };

peopleRepository.Add(people);          // ITransaction.Begin() ISession.Save(people)
organizationRepository.Add(org);       // ISession.Save(org)
peopleOrganizationRepository.Add(po);  // ISession.Save(po)

unitOfWork.Commit();                   // ITransaction.Commit()

Мои вопросы:

  1. Являются ли мои сопоставленияПравильно ли настроен для поддержки такого сценария «многие ко многим»?
  2. Есть ли у меня способ просто сделать следующее (что будет записывать во все три таблицы):

-

People people = new People { FirstName = "firstname" };
Organization org = new Organization { Name = "org" };
PeopleOrganization po = new PeopleOrganization { People = people, Organization = org, Details = "details" };

peopleRepository.Add(people);          // Just ONE ISession.Save(people)

unitOfWork.Commit();                   // ITransaction.Commit()

Любой вклад высоко ценится.

Спасибо

1 Ответ

1 голос
/ 15 декабря 2010

Во-первых, вам нужно добавить вновь созданную PeopleOrganization в коллекцию на обеих сущностях (Organization и People). Затем, если вы добавите Cascade.All() к вашей HasMany цепочке, сохранения должны распространяться (каскадно) до PeopleOrganization, а затем до Organization.

В качестве чисто семантического предложения я бы порекомендовал инкапсулировать создание PeopleOrganization в метод на Person. Примерно так:

class Person
{
  public void AddOrganization(Organization org, string details)
  {
    var link = new PeopleOrganization { ... };

    LinkToOrganization.Add(link)
    org.LinkToPeople.Add(link);
  }
}

Таким образом, вам никогда не придется самостоятельно создавать внутреннюю сущность.

...