2013-04-04 82 views
4

我的实体映射实体有一些原因没有主键:NHibernate的无主键

public partial class VehicleLocation 
{ 
    public virtual string UserCode { get; set; } 
    public virtual string DateTime { get; set; } 
    public virtual string Device { get; set; } 
    public virtual string Gps { get; set; } 
    public virtual string GpsDateTime { get; set; } 
    public virtual double Speed { get; set; } 
} 

映射:

class VehicleLoactionMap : ClassMap<VehicleLocation> 
{ 
    public VehicleLoactionMap() 
    { 
     Table("VEHICLE_LOCATION"); 
     LazyLoad(); 
     Map(x => x.UserCode).Column("USER_CODE"); 
     Map(x => x.DateTime).Column("DATE_TIME"); 
     Map(x => x.Device).Column("DEVICE"); 
     Map(x => x.Gps).Column("GPS"); 
     Map(x => x.GpsDateTime).Column("GPS_DATE_TIME"); 
     Map(x => x.Speed).Column("SPEED"); 
    } 
} 

我得到这个错误:

The entity 'VehicleLocation' doesn't have an Id mapped...

如何映射我的实体而不使用主键?

+1

没有PK的原因是什么?如果仅仅是传统数据库模式的情况下,你不能改变,那么你必须看看复合键(尽管这会让事情变得棘手)。但除此之外,即使它只是代理键,我也看不到没有PK的好理由。把一个,你的NHibernate问题消失。 – 2013-04-04 10:08:40

+0

使用我无法更改的预定义数据库模式。我无法添加/删除键/字段..在我的数据库是这个表没有一个PK,我试图映射它,你可以在我的示例代码中看到。 – Stacked 2013-04-04 10:37:26

+0

唉,这是一个令人失望:-(我有以下建议,那么复合键的方法去。 – 2013-04-04 11:08:53

回答

6

我有同样的问题而回,但很多搜索后,我发现这是不可能有没有标识符字段实体NHibernate的映射。

但是,您可以通过使用组合键而不是唯一标识符来实现。虽然我自己没有尝试过。

Here是回答类似的问题,可以帮助你。

2

没有这样做,例如NHibernate的方式需要为每个实体的唯一标识符。这是因为NHibernate需要一种方法将数据库表中的一行数据绑定到实体。如果它不能做到这一点,那么它就没有办法对实体数据执行任何形式的持久性。

在该表中没有一个主键我已经找到工作的两种可能的方法的情况。

  1. 使用复合主键。

  2. 如果你的DBMS支持您可以使用物理行标识。 SQL Server 2008有%%physloc%%和Oracle有ROWID

但我真的不会在几乎任何情况下都推荐选项2。这是因为DBMS不保证行ID在行的生命周期中保持不变,因此是非常不可靠的主键。

+0

'%% physloc %%'是没有文档,听起来像一个愚蠢的想法。1)加载实体具有给定值'%% physloc %%'2)索引维护运行3)'%% physloc %%'现在不同。 – 2013-10-24 01:25:59

+0

@ ta.speot.is我同意在99.9%的情况下使用%% physloc %%是一个糟糕的主意。但有时在处理遗留数据库时,无法更改架构,这是唯一的选择。尽管你说得很好,所以我已经更新了我的答案以反映它 – mickfold 2013-10-24 15:16:29

0

易于创建组合键。 代码示例(VB):

Table("Table1") 
CompositeId().KeyProperty(Function(x) x.Field1).KeyProperty(Function(x) x.Field2)