开发者

One-to-one mapping in S#arp Architecture

开发者 https://www.devze.com 2023-01-28 21:57 出处:网络
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.

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#.

0

精彩评论

暂无评论...
验证码 换一张
取 消