NHibernate错误地创建了ManyToMany表 - 无法在可空列错误上定义PRIMARY KEY约束

时间:2012-07-01 22:36:07

标签: sql-server nhibernate fluent-nhibernate

我刚开始在我的项目中实现ISet而不是IList,因为这更好地反映了我的收藏品。

这在创建一个表时引发了一个奇怪的错误。我得到的错误是。

  

无法在表'UserAddressAssignments'中的可空列上定义PRIMARY KEY约束。

我在用户和地址之间有很多关系。

public class User : BaseEntity
{
    public virtual System.Guid UserGuid { get; set; }
    public virtual string UserName { get; set; }
    public virtual Company Company { get; set; }
    public virtual Iesi.Collections.Generic.ISet<Address> UserAddressAssignments { get; set; }
}

它为查阅列生成的SQL导致了问题,如下所示。 UserId列可以为空,导致问题。

create table UserAddressAssignments (
    UserAddressAssignmentId INT not null,
   AddressId INT IDENTITY NOT NULL,
   UserId INT null,
   primary key (UserId, AddressId)
)

这里奇怪的部分是我在公司和地址之间有相同的关系,工作正常。

public class Company : BaseEntity
{
    public virtual System.Guid CompanyGuid { get; set; }
    public virtual string Name { get; set; }
    public virtual Iesi.Collections.Generic.ISet<Address> CompanyAddressAssignments { get; set; }
}

这为查找表创建了正确的SQL。

CREATE TABLE [dbo].[CompanyAddressAssignments](
    [CompanyId] [int] NOT NULL,
    [AddressId] [int] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [CompanyId] ASC,
    [AddressId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

使用具有键的正确非空属性的聚簇键,并且没有与用户查找列一样的第三个“CompanyAddressAssignmentId”列。

公司和用户的映射覆盖也是相同的。

public class CompanyMappingOverride : IAutoMappingOverride<Company>
{
        public void Override(FluentNHibernate.Automapping.AutoMapping<Company> mapping)
        {
            mapping.Map(x => x.Name);
            mapping.HasManyToMany(x => x.CompanyAddressAssignments).Table("CompanyAddressAssignments").Cascade.All();
        }
}

public class UserMappingOverride : IAutoMappingOverride<User>
{
    public void Override(FluentNHibernate.Automapping.AutoMapping<User> mapping)
    {
        mapping.References(x => x.Company).Cascade.All();
        mapping.HasManyToMany(x => x.UserAddressAssignments).Table("UserAddressAssignments").Cascade.All();
    }
}

有没有人对两个查找表看起来如此不同的原因有任何建议,只要我可以告诉结构和类的映射是相同的?

我现在使用IList用户地址来解决此问题。

这就产生了这个创建sql的问题。

CREATE TABLE [dbo].[CompanyAddressAssignments](
    [CompanyId] [int] NOT NULL,
    [AddressId] [int] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [CompanyId] ASC,
    [AddressId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

关于可能导致这种差异的任何想法?

NHibernate版本是3.2.0.4000。

干杯

史蒂夫

1 个答案:

答案 0 :(得分:0)

对,我发现了问题所在。

我正在研究的网站已经添加了NHibernate。为了使用代码优先/模式生成方法,我使用了一个自动化工具将现有模式转换为可以从中神奇地创建模式的类。

我使用NHhibernate设计器自动生成类,然后清理实体以符合我们的标准。

http://www.devart.com/entitydeveloper/nhibernate-designer.html

当工具为查找表生成一个类时,错误就会出现。因此UserAddressAssignment在系统中有自己的类。在创建多对多关系时,通常不需要这样做。在指定了ManyToMany表的名称的情况下,指定了多对多的类以及ALSO在映射覆盖中,NHibernate必须混淆(不出所料)。

我想指出的是,NHibernate Designer必须使用的模式并不是所有那些没有强制执行的关系,所以我不会因为在不需要时创建这个实体而责备它!

所以当我删除下面给出的不必要的UserAddressAssignment类时,一切都按预期工作。

  public class UserAddressAssignment : BaseEntity
    {
        public virtual int AddressId { get; set; }
        public virtual User User { get; set; }
        public virtual Address Address { get; set; }
    }

希望这有助于一个人!

干杯

史蒂夫