There's a distinct smell of burned out circuits coming from my head, so forgive my ignorance.
I'm trying to setup a one-to-one relationship (well, let Automapper do it) in S#arp Architecture.
I have
public class User : Entity
{
public virtual Profile Profile { get; set; }
public virtual Basket Basket { get; set; }
public virtual IList<Order> Orders { get; set; }
public virtual IList<Role> Roles { get; set; }
...
}
public class Basket : Entity
{
public virtual User User { get; set; }
...
}
public class Profile : Entity
{
public virtual User User { get; set; }
...
}
And my db schema is
CREATE TABLE [dbo].[Users](
[Id] [int] IDENTITY(1,1) NOT NULL,
...
CREATE TABLE [dbo].[Profiles](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserFk] [int] NULL,
...
CREATE TABLE [dbo].[Baskets](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserFk] [int] NULL,
...
When I run the unit test CanConfirmDatabaseMatchesMappings in MappingIntegrationTests I get the following error
NHibernate.ADOException : could not execute query ... System.Data.SqlClient.SqlException : Invalid column name 'ProfileFk'. Invalid column name 'BasketFk'.
and the sql it's trying to execute is
SELECT TOP 0
this_.Id AS Id6_1_ ,
..
开发者_C百科 user2_.ProfileFk AS ProfileFk9_0_ ,
user2_.BasketFk AS BasketFk9_0_
FROM
Profiles this_
LEFT OUTER JOIN Users user2_
ON this_.UserFk = user2_.Id
So it's looking for a ProfileFk and BasketFk field in the Users table. I haven't setup any customer override mappings and as far as I can see I've followed the default conventions setup in S#.
The two other mappings for IList Orders and Roles seem to map fine. So I'm guessing that it've missed something for setting up a one-to-one relationship.
What am I missing?
Got it. This is really an NHibernate problem to solve with Fluent NHibernate syntax, but it happens to be relevant for S#.
Background reading: NHibernate Mapping and Fluent NHibernate HasOne
What you do is override the mapping for User and give it two .HasOne mappings. Then set a unique reference to the user on the Profile and Basket class:
public class UserMap : IAutoMappingOverride<User>
{
#region Implementation of IAutoMappingOverride<User>
/// <summary>
/// Alter the automapping for this type
/// </summary>
/// <param name="mapping">Automapping</param>
public void Override(AutoMapping<User> mapping)
{
mapping.HasOne(u => u.Profile);
mapping.HasOne(u => u.Basket);
}
#endregion
}
public class ProfileMap : IAutoMappingOverride<Profile>
{
#region Implementation of IAutoMappingOverride<Profile>
/// <summary>
/// Alter the automapping for this type
/// </summary>
/// <param name="mapping">Automapping</param>
public void Override(AutoMapping<Profile> mapping)
{
mapping.References(p => p.User).Unique().Column("UserFk");
}
#endregion
}
public class BasketMap : IAutoMappingOverride<Basket>
{
#region Implementation of IAutoMappingOverride<Basket>
/// <summary>
/// Alter the automapping for this type
/// </summary>
/// <param name="mapping">Automapping</param>
public void Override(AutoMapping<Basket> mapping)
{
mapping.References(b => b.User).Unique().Column("UserFk");
}
#endregion
}
As a side note, at the time of writing this, NHibernate 3 has just been released. There's a great book out called NHibernate 3.0 Cookbook which I've just bought and it looks extremely useful for working with S#.
精彩评论