现在的位置: 首页 > 综合 > 正文

关于SQL-Server的多主键约束问题

2012年09月04日 ⁄ 综合 ⁄ 共 1726字 ⁄ 字号 评论关闭
上个星期开发时发现一个问题~~在用Nhibernate的时候,一表多约束的问题卡了一天时间,可能是基础不好~对联合主键和Nhibernate使用不熟练,搞了一天,浪费了一天
Nhibernate使用联合主键十分复杂(个人觉得!),而且偶师兄也强烈反对使用联合主键。
联合主键实际上也不适合我的需要(只是不知道乱78找,看到了这个东西,觉得可以在当前项目上,就研究了一下。)
其实一开始对这个概念也挺模糊的,找了一大堆资料之后,总结如下(如有错误请指正)
联合主键是把一个表的主键和外键(或其他任意2个或2个以上的键作为联合主键,当然需要符合主键的约束。)就是生成新的主键(概念上),作为引索。
主要适用于多用户的文件管理。(例如简单的网络硬盘)
id为表主键,username用户名要进行约束(避免重复),FileName为上传的用户自定义文件名,每个用户自己的文件名是不能重复的。
这样的结构
表1:user表
id(PK_key/FK) username(U)
1 aaa
2 bbb

表2:file表

id(PK_key) u_id(U) FileName
1 1 test.jpg
2 1 abc.jpg

以上的数据是合理的,而且无违反任何约束。

然而数据如果是这样:

id(PK_key/FK) username(U)
1 aaa
2 bbb

 

id(PK_key) u_id(U) FileName
1 1 test.jpg
2 2 test.jpg

这样子就不能对FileName做单一约束。
解决方案有两种:1联合主键联合u_id和FileName。
2用多键约束。
由于联合主键在Nhibernate上实在难用,也不好用。要生成一个新的实体类。而且操作复杂。感觉上很无谓。而且Nhibernate也不推荐。Nhibernate的定义如下:

联合ID(composite-id)

<composite-id
	name="propertyName"(1)
	class="ClassName"(2)
	unsaved-value="any|none"(3)
	access="field|property|nosetter|ClassName">

	<key-property name="propertyName" type="typename" column="column_name"/>
	<key-many-to-one name="propertyName class="ClassName" column="column_name"/>
	......
</composite-id>

如果表使用联合主键,你可以把类的多个属性组合成为标识符属性。<composite-id>元素接受<key-property>属性映射和<key-many-to-one>属性映射作为子元素。

<composite-id>
	<key-property name="medicareNumber"/>
	<key-property name="dependent"/>
</composite-id>

你的持久化类必须重载Equals()HashCode()方法,来实现组合的标识符判断等价.也必须实现Serializable接口

不幸的是,这种组合关键字的方法意味着一个持久化类是它自己的标识。除了对象自己之外,没有什么方便的“把手”可用。你必须自己初始化持久化类的实例,在使用组合关键字Load()持久化状态之前,必须填充他的联合属性。我们会在TODO:LINKTOCOMPENENTS中说明一种更加方便的方法,把联合标识实现为一个独立的类,下面描述的属性只对这种备用方法有效:

(1)

name (可选): 一个组件类型,持有联合标识(参见下一节)。

(2)

class (可选 - 默认为通过反射(reflection)得到的属性类型): 作为联合标识的组件类名(参见下一节)。

(3)

unsaved-value (可选 - 默认为 none): 假如被设置为any的值,就表示新创建,尚未被持久化的实例将持有的值。

(载自http://www.cnblogs.com/renrenqq

调试得我发飙~

最后还是使用了多键约束,简单方便。由sql自己去判断。
建立了u_id和FileName联合约束,就解决了这个问题:)。

抱歉!评论已关闭.