功能NHibernate复合ID表问题 [英] Fluent NHibernate Composite ID table problem

查看:100
本文介绍了功能NHibernate复合ID表问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点新NHibernate和我遇到了一个问题。
我有以下表格:



表1:
表格名称:用户,
第1列: ID,
2列:命名



表格2:
表格名称:任务,
第1列: ID,
2列:说明



表3:
表格名称: UserToDoMissions,
第1列:用户名,
2列: MissionID,
3列:等级



下面是代码:
MissionMap:

 公共类MissionMap:ClassMap<使命> 
{
公共常量字符串表名=tblMissions;
公共常量字符串C_ID =achID;
公共常量字符串c_name =achName;

公共MissionMap()
{
表(表名);
ID(X => x.ID).Column(C_ID).Not.Nullable();
地图(X => x.Name).Column(c_name).Not.Nullable();

的hasMany(X => x.UserToDoList)。.Cascade.All()反()KeyColumn(UserToDoMap.c_missionID)。
}
}



用户地图:

 公共类中userMap:ClassMap<使用者> 
{
公共常量字符串表名=向tblUsers;
公共常量字符串C_ID =usrID;
公共常量字符串c_userName =usrUserName;

公众用户映射()
{
表(表名);
ID(X => x.ID).Column(C_ID).Not.Nullable();
地图(X => x.UserName).Column(c_userName).UniqueKey(DBConsts.UniqueKeys.User_UserName).Not.Nullable();

的hasMany(X => x.UserToDoList)。.Cascade.All()反()KeyColumn(UserToDoMap.c_userID)。
}
}



UserToDo图:

 公共类UserToDoMap:ClassMap< UserToDo> 
{
公共常量字符串表名=tblToDoList;
公共常量字符串c_userID =tdlUserID;
公共常量字符串c_missionID =tdlMissionID;
公共常量字符串c_rank =tdlRank;

公共UserToDoMap()
{
表(表名);
CompositeId()KeyReference(X => x.User,c_userID).KeyReference(X => x.Achievment,c_missionID);
引用(X => x.User).Column(c_userID).Cascade.All()唯一键(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable()。
引用(X => x.Mission).Column(c_missionID).Cascade.All()Not.Nullable()。
地图(X => x.Rank).Column(c_rank).UniqueKey(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable();
}
}



我的问题是,我可以;吨保存新线。我可以选择,并得到所有的东西,但无法保存。 ?
任何想法



感谢



编辑:
我没有变任何东西。不会抛出异常,但该行不会被添加到数据库。
顺便说一句,我使用UserToDo对象的保存方法



编辑2:
这里docmanhattan答案后是代码:



UserToDoMap:

 公共类UserToDoMap:ClassMap< UserToDo> 
{
公共常量字符串表名=tblToDoList;
公共常量字符串c_userID =tdlUserID;
公共常量字符串c_missionID =tdlMissionID;
公共常量字符串c_rank =tdlRank;

公共UserToDoMap()
{
表(表名);
CompositeId< UserToDoId>(X => x.ID)
.KeyReference(X => x.UserIdPart,c_userID)
.KeyReference(X => x.MissionIdPart,c_missionID );
引用(X => x.ID.UserIdPart).Column(c_userID).Cascade.All()唯一键(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable()。
引用(X => x.ID.MissionIdPart).Column(c_missionID).Cascade.All()Not.Nullable()。
地图(X => x.Rank).Column(c_rank).UniqueKey(DBConsts.UniqueKeys.ToDoList_UserRanks).Not.Nullable();
}
}



UserToDoId实体:

 公共类UserToDoId 
{
公共虚拟用户UserIdPart {搞定;组; }
公共虚拟使命MissionIdPart {搞定;组; }

公众覆盖布尔等于(obj对象)
{
UserToDoId recievedObject =(UserToDoId)目标文件;

如果((UserIdPart.ID == recievedObject.UserIdPart.ID)及&放大器;
(MissionIdPart.ID == recievedObject.MissionIdPart.ID))
{
返回(真);
}

返回(假);
}

公共覆盖INT的GetHashCode()
{
返回base.GetHashCode();
}
}



UserToDo实体:

 公共类UserToDo 
{
公共虚拟UserToDoId ID {搞定;组; }

公共虚拟INT排名{搞定;组; }

公共UserToDo()
{

}

公众覆盖布尔等于(obj对象)
{
UserToDo recievedObject =(UserToDo)目标文件;

如果((ID.UserIdPart.ID == recievedObject.ID.UserIdPart.ID)及&放大器;
(ID.MissionIdPart.ID == recievedObject.ID.MissionIdPart.ID) &功放;&安培;
(等级== recievedObject.Rank))
{
返回(真);
}

返回(假);
}

公共覆盖INT的GetHashCode()
{
返回base.GetHashCode();
}
}



我发现了异常,当我试图创建会话工厂:




{找不到类财产UserIdPart'DatabaseEntities.UserToDo吸气}



解决方案

我有很多问题与IDS的复合,如做事<一个HREF =htt​​p://stackoverflow.com/questions/6837816/cannot-merge-an-entity-with-a-composite-id-when-that-entity-has-been-previously-r/6865043#6865043>这。我建议你​​做什么,我所做的是创建一个新类型,只是包含什么复合ID使用的ID,然后像映射会这样:

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



在哪里UserToDoId在复合ID使用的两个参考:

 公共类UserToDoId 
{
的用户UserIdPart {搞定;组; }
成就AchievementIdPart {搞定;组; }

公众覆盖布尔等于(obj对象)
{
返回等于(OBJ为UserToDoId);
}

私人布尔等于(UserToDoId等)
{
如果(的ReferenceEquals(其他,NULL))返回false;
如果(的ReferenceEquals(其它,这一点))返回true;

返回UserIdPart.ID == other.UserIdPart.ID&放大器;&安培;
MissionIdPart.ID == other.MissionIdPart.ID;
}

公共覆盖INT的GetHashCode()
{
选中
{
INT哈希=的GetType()GetHashCode()方法。
哈希=(散列* 31)^ UserIdPart.ID.GetHashCode();
哈希=(散列* 31)^ MissionIdPart.ID.GetHashCode();

返回哈希;
}
}
}



我不知道为什么,但也有一堆弹出,当你不使用另一种类型,以承载组件的id件小问题。



有一个问题我曾在联在我的答案的开始。另外一个我用的复合ID与子类映射的父抽象类将尝试创建某些查询抽象类的实例(你不能这样做)。实施这种新型固定这两个问题。



给它一个尝试,看看是否能工程。此外,achievment拼写成就(不是要嘲讽,我只希望你会避免人拼写错误:-D的代码原因窃笑)


I'm kinda new to nhibernate and i ran into a problem. I have the following tables:

Table 1: Table Name: Users, Column 1: ID, Column 2: Name

Table 2: Table Name: Missions, Column 1: ID, Column 2: Description

Table 3: Table Name: UserToDoMissions, Column 1: UserID, Column 2: MissionID, Column 3: Rank

Here is the code: 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);
    }
}

User Map:

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 Map:

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();
    }
}

My problem is that i can;t save a new line. I can select and get all of the things but can't save. Any ideas?

Thanks.

Edit: I'm not getting anything. No exception is thrown but the row isn't added to the DB. BTW, I'm using the save method on UserToDo object.

Edit 2: After docmanhattan answer here is the code:

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 entity:

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();
    }
}

I'm getting the exception when i'm trying to create the session factory:

{"Could not find a getter for property 'UserIdPart' in class 'DatabaseEntities.UserToDo'"}

解决方案

I've had lots of problems with doing things with composite ids, such as this. I'd suggest doing what I did which is create a new type that just encompasses what the composite id uses for the id and then mapping it like so:

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

Where UserToDoId has the two references used in the composite id:

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;
        }
    }
}

I have no idea why, but there are a bunch of little problems that pop up when you don't use another type to hold the pieces of the component id.

One problem I had was linked at the beginning on my answer. Another one I had was using a composite id for a parent abstract class with subclass mappings would attempt to create instances of the abstract class (which you can't do) for certain queries. Implementing this new type fixed both of these problems.

Give it a try and see if that works. Also, 'achievment' is spelled 'achievement' (not trying to taunt, I just hope you'll avoid people snickering at your code cause of a spelling error :-D)

这篇关于功能NHibernate复合ID表问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆