简体   繁体   中英

Fluent NHibernate Mapping Help static view referencing with compositeID

Afternoon all. I'm trying to create a mapping for a flight segment database where at the bottom of the mapping tree a FlightSegment references an origin and destination table with a compositeID consisting of a three letter code and a Boolean determining whether the code is or isn't a city.

Below are the relevant simplified class structures:

    public class GTIFlightSegment
        {
            public virtual int ID { get; protected set; }


            public virtual GTIOriginAirport Origin { get; set; }
            public virtual GTIDestinationAirport Destination { get; set; }

            public virtual GTIFlightSegmentGroup Parent { get; set; }

        }

  public class GTIAirport
    {

        public virtual string Code { get; set; }
        public virtual string Name { get; set; }
        public virtual  string City { get; set; }
        public virtual string CountryCode { get; set; }
        public virtual GTIGeoCode GeoCode {get; set; }
        public virtual string Terminal { get; set; }
        public virtual bool IsCity { get; set; }
        public GTIAirport()
        {
            GeoCode = new GTIGeoCode();
            IsCity = false;
        }

        public override bool Equals(object obj)
        {
            var other = obj as GTIAirport;

            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;

            return this.Code == other.Code && this.IsCity == other.IsCity;
        }


        public override int GetHashCode()
        {
            unchecked
            {
                int hash = GetType().GetHashCode();
                hash = (hash * 31) ^ Code.GetHashCode();
                hash = (hash * 31) ^ IsCity.GetHashCode();

                return hash;
            }
        }

    }

    public class GTIOriginAirport : GTIAirport
    {
        public virtual GTIFlightSegment Parent { get; set; }

        public GTIOriginAirport() : base()
        {

        }
    }

    public class GTIDestinationAirport : GTIAirport
    {

        public virtual GTIFlightSegment Parent { get; set; }

        public GTIDestinationAirport() : base()
        {

        }
    }

And below are the mappings I've created so far for the objects:

public class GTIFlightSegmentMap : ClassMap<GTIFlightSegment>
    {
        public GTIFlightSegmentMap()
        {
            Id(x => x.ID);

            References(x => x.Destination).Columns(new string[] { "DestinationCODE", "DestinationIsCity" }).Cascade.All();
            References(x => x.Origin).Columns(new string[] { "OriginCODE", "OriginIsCity"}).Cascade.All();

            References(x => x.Parent).Not.Nullable();


        }
    }


 public class GTIAirportMap : ClassMap<GTIAirport>
    {
        public GTIAirportMap()
        {
            Table("GTIAirport");
            ReadOnly();
            CompositeId()
                .KeyProperty(x => x.Code, "CODE")
                .KeyProperty(x => x.IsCity, "isCity");                 

            Map(x => x.Name).Column("Airport");
            Map(x => x.City);
            Map(x => x.CountryCode);
            Component(x => x.GeoCode, m =>
            {
                m.Map(x => x.Latitude);
                m.Map(x => x.Longitude);

            });

        }

    }

    public class GTIOriginAirportMap : SubclassMap<GTIOriginAirport>
    {
        public GTIOriginAirportMap()
        {
            KeyColumn("CODE");
            KeyColumn("isCity");
            HasOne(x => x.Parent).PropertyRef(x => x.Origin);
        }
    }


    public class GTIDestinationAirportMap : SubclassMap<GTIDestinationAirport>
    {
        public GTIDestinationAirportMap()
        {
            KeyColumn("CODE");
            KeyColumn("isCity");
            HasOne(x => x.Parent).PropertyRef(x => x.Origin);
        }
    }

What I'm trying to achieve is that when a FlightSegment is created in the system it will store the DestinationIsCity/DestinationCode and the OriginIsCity/OriginCode in the flight segments table but not try and update the GTIAirport reference table view. But when the objects are retrieved from the database with a query over, the rich information from the GTIAirport reference table will be fetched.

Or possibly have the Code and IsCity in the DepartureAirport and OriginAirport tables respectively with a ID reference back to the flight segment.

No matter what connotations I'm trying I'm hitting a wall of some kind. Basically I've got myself in a bit of a mess. I've flipped the relationships between the Airport and segment, swapping out to only references. Cascaded, not cascaded.

Common Errors being encountered whilst playing with the mappings:

1) The UPDATE statement conflicted with the FOREIGN KEY constraint

2) {"broken column mapping for: Destination.id of: GilesSabreConnection.Profiling.Model.BookingEngineModel.Model.GTIFlightSegment, type component[Code,IsCity] expects 2 columns, but 1 were mapped"}

3) {"Foreign key (FK582A9C81E6C3913B:GTIFlightSegment [Destination_id])) must have same number of columns as the referenced primary key (GTIDestinationAirport [CODE, isCity])"}

In case it's needed the fluent config is:

return Fluently.Configure().Database(MsSqlConfiguration.MsSql2012.ConnectionString(@"Data Source=Dev2;Initial Catalog=Sandbox;Integrated Security=True")).Mappings(m => m.FluentMappings.AddFromAssemblyOf<Profile>()).ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(true, true)).BuildSessionFactory();

Any help to point me in the right direction from the database and fluent gurus would be greatly appreciated.

Many thanks in advance.

Realised that by setting the GTIAirport Map as readonly I was inherently making the Destination and Origin maps as readonly so the mapping could never work no matter how I was configuring the relationships.

So I've split the static reference database of detailed airport info accessed via the View named GTIAiport into two, so the Boolean in the composite key is no longer required. I now have the flight segment mapping simply logging the Airport origin/destination codes within the flight segment table using the Component class in fluent. In the Airport class itself now have a function to independently fetch the rich data from the static reference database table on request using the stored Airport code.

Couldn't figure out a way to do this with fluent. Interested to know if there is a way.

public GTIFlightSegmentMap()
        {
            Id(x => x.ID);

            Component(x => x.Destination, m =>
            {
                m.Map(y => y.Code).Column("DestinationCode");

            });
            Component(x => x.Origin, m =>
            {
                m.Map(y => y.Code).Column("OriginCode");

            });
           ;       
            References(x => x.Parent).Not.Nullable();


        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM