Неполная проблема с таблицей составных идентификаторов NHibernate - PullRequest
2 голосов
/ 15 августа 2011

Я новичок в nhibernate и столкнулся с проблемой.У меня есть следующие таблицы:

Таблица 1: Имя таблицы: Пользователи, Столбец 1: ID, Столбец 2: Имя

Таблица 2: Имя таблицы: Миссии, Столбец 1: ID, Столбец 2: Описание

Таблица 3: Имя таблицы: UserToDoMissions, Столбец 1: UserID, Столбец 2: MissionID, Столбец 3: Rank

Вот код: MissionMap:

public class MissionMap : ClassMap<Mission>
{
    public const string TableName = "tblMissions";
    public const string c_id = "achID";
    public const string c_name = "achName";

    public MissionMap()
    {
        Table(TableName);
        Id(x => x.ID).Column(c_id).Not.Nullable();
        Map(x => x.Name).Column(c_name).Not.Nullable();

        HasMany(x => x.UserToDoList).Cascade.All().Inverse().KeyColumn(UserToDoMap.c_missionID);
    }
}

Карта пользователя:

public class UserMap : ClassMap<User>
{
    public const string TableName = "tblUsers";
    public const string c_id = "usrID";
    public const string c_userName = "usrUserName";

    public UserMap()
    {
        Table(TableName);
        Id(x => x.ID).Column(c_id).Not.Nullable();
        Map(x => x.UserName).Column(c_userName).UniqueKey(DBConsts.UniqueKeys.User_UserName).Not.Nullable();

        HasMany(x => x.UserToDoList).Cascade.All().Inverse().KeyColumn(UserToDoMap.c_userID);
    }
}

Карта UserToDo:

public class UserToDoMap : ClassMap<UserToDo>
{
    public const string TableName = "tblToDoList";
    public const string c_userID = "tdlUserID";
    public const string c_missionID = "tdlMissionID";
    public const string c_rank = "tdlRank";

    public UserToDoMap()
    {
        Table(TableName);
        CompositeId().KeyReference(x => x.User, c_userID).KeyReference(x => x.Achievment, c_missionID);
        References(x => x.User).Column(c_userID).Cascade.All().UniqueKey(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable();
        References(x => x.Mission).Column(c_missionID).Cascade.All().Not.Nullable();
        Map(x => x.Rank).Column(c_rank).UniqueKey(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable();
    }
}

Моя проблема в том, что я не могу сохранить новую строку.Я могу выбрать и получить все вещи, но не могу сохранить.Есть идеи?

Спасибо.

Редактировать: Я ничего не получаю.Не выдается никаких исключений, но строка не добавляется в БД.Кстати, я использую метод сохранения для объекта UserToDo.

Редактировать 2: После ответа docmanhattan вот код:

UserToDoMap:

public class UserToDoMap : ClassMap<UserToDo>
{
    public const string TableName = "tblToDoList";
    public const string c_userID = "tdlUserID";
    public const string c_missionID = "tdlMissionID";
    public const string c_rank = "tdlRank";

    public UserToDoMap()
    {
        Table(TableName);
        CompositeId<UserToDoId>(x => x.ID)
            .KeyReference(x => x.UserIdPart, c_userID)
            .KeyReference(x => x.MissionIdPart, c_missionID);
        References(x => x.ID.UserIdPart).Column(c_userID).Cascade.All().UniqueKey(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable();
        References(x => x.ID.MissionIdPart).Column(c_missionID).Cascade.All().Not.Nullable();
        Map(x => x.Rank).Column(c_rank).UniqueKey(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable();
    }
}

UserToDoId entity

public class UserToDoId
{
    public virtual User UserIdPart { get; set; }
    public virtual Mission MissionIdPart { get; set; }

    public override bool Equals(object obj)
    {
        UserToDoId recievedObject = (UserToDoId)obj;

        if ((UserIdPart.ID == recievedObject.UserIdPart.ID) &&
            (MissionIdPart.ID == recievedObject.MissionIdPart.ID))
        {
            return (true);
        }

        return (false);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

Сущность UserToDo:

public class UserToDo
{
    public virtual UserToDoId ID { get; set; }

    public virtual int Rank { get; set; }

    public UserToDo()
    {

    }

    public override bool Equals(object obj)
    {
        UserToDo recievedObject = (UserToDo)obj;

        if ((ID.UserIdPart.ID == recievedObject.ID.UserIdPart.ID) &&
            (ID.MissionIdPart.ID == recievedObject.ID.MissionIdPart.ID) &&
            (Rank == recievedObject.Rank))
        {
            return (true);
        }

        return (false);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

При попытке создать фабрику сеанса я получаю исключение:

{"Couldне найден метод получения свойства 'UserIdPart' в классе 'DatabaseEntities.UserToDo' "}

1 Ответ

5 голосов
/ 16 августа 2011

У меня было много проблем с работой с составными идентификаторами, такими как this .Я бы предложил сделать то, что я сделал, - создать новый тип, который просто включает в себя то, что композитный идентификатор использует для идентификатора, и затем отобразить его следующим образом:

CompositeId<UserToDoId>(x => x.ID)
    .KeyReference(x => x.UserIdPart, c_userID)
    .KeyReference(x => x.AchievementIdPart, c_missionID);

Где UserToDoId имеет две ссылки, используемые всоставной идентификатор:

public class UserToDoId
{
    User UserIdPart { get; set; }
    Achievement AchievementIdPart { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as UserToDoId);
    }

    private bool Equals(UserToDoId other)
    {
        if (ReferenceEquals(other, null)) return false;
        if (ReferenceEquals(other, this)) return true;

        return UserIdPart.ID == other.UserIdPart.ID &&
            MissionIdPart.ID == other.MissionIdPart.ID;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = GetType().GetHashCode();
            hash = (hash * 31) ^ UserIdPart.ID.GetHashCode();
            hash = (hash * 31) ^ MissionIdPart.ID.GetHashCode();

            return hash;
        }
    }
}

Понятия не имею почему, но возникает множество небольших проблем, которые возникают, когда вы не используете другой тип для хранения частей идентификатора компонента.

Одна проблема, с которой я столкнулся, была связана в начале моего ответа.Другой, который я использовал, использовал составной идентификатор для родительского абстрактного класса с сопоставлениями подклассов, пытаясь создать экземпляры абстрактного класса (что вы не можете сделать) для определенных запросов.Реализация этого нового типа исправила обе эти проблемы.

Попробуйте и посмотрите, работает ли это.Кроме того, «достижение» означает «достижение» (не пытаясь насмехаться, я просто надеюсь, что вы избежите смеха людей над вашим кодом из-за орфографической ошибки :-D)

...