Note that there are some explanatory texts on larger screens.

plurals
  1. POBreeze: Differences between Entity Framework and NHibernate with many to many
    primarykey
    data
    text
    <p>Here is the situation:</p> <ul> <li>WebApi v1</li> <li>Breeze 1.4.7</li> <li>EF 5.0/NHibernate 3.3.1</li> </ul> <p>What We want: A many to many exposed as a many to one. A client can have multiple countries and a country can have multiple clients. A ClientCountry entity has been created for that purpose.</p> <p>My mapping looks like this:</p> <p>Entity Framework:</p> <pre><code> modelBuilder.Entity&lt;Client&gt;().HasKey(p =&gt; p.Id).Property(p=&gt;p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); modelBuilder.Entity&lt;Client&gt;().Property(p =&gt; p.Abbreviation); modelBuilder.Entity&lt;Client&gt;().Property(p =&gt; p.ClientSinceDate).IsRequired(); modelBuilder.Entity&lt;Client&gt;().Property(p =&gt; p.ClientUntilDate); modelBuilder.Entity&lt;Client&gt;().Property(p =&gt; p.Name).IsRequired(); modelBuilder.Entity&lt;Client&gt;().Property(p =&gt; p.Website); modelBuilder.Entity&lt;Client&gt;().HasMany(p =&gt; p.Contacts).WithRequired(p =&gt; p.Client).WillCascadeOnDelete(true); modelBuilder.Entity&lt;Client&gt;().HasMany(p =&gt; p.ClientCountries).WithRequired(p =&gt; p.Client).WillCascadeOnDelete(true); modelBuilder.Entity&lt;Contact&gt;().HasKey(p =&gt; p.Id).Property(p =&gt; p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); modelBuilder.Entity&lt;Contact&gt;().Property(p =&gt; p.Username); modelBuilder.Entity&lt;Contact&gt;().HasRequired(p =&gt; p.Client); modelBuilder.Entity&lt;Country&gt;().HasKey(p =&gt; p.Id).Property(p =&gt; p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); modelBuilder.Entity&lt;Country&gt;().Property(p =&gt; p.ValidFrom); modelBuilder.Entity&lt;Country&gt;().Property(p =&gt; p.ValidTo); modelBuilder.Entity&lt;Country&gt;().Property(p =&gt; p.Code); modelBuilder.Entity&lt;Country&gt;().Property(p =&gt; p.DefaultLabel); modelBuilder.Entity&lt;Country&gt;().Property(p =&gt; p.Description); modelBuilder.Entity&lt;Country&gt;().Property(p =&gt; p.DisplayOrder); modelBuilder.Entity&lt;ClientCountry&gt;().HasKey(p =&gt; p.Id).Property(p =&gt; p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); modelBuilder.Entity&lt;ClientCountry&gt;().Property(p =&gt; p.ValidFrom); modelBuilder.Entity&lt;ClientCountry&gt;().Property(p =&gt; p.ValidTo); modelBuilder.Entity&lt;ClientCountry&gt;().HasRequired(p =&gt; p.Client); modelBuilder.Entity&lt;ClientCountry&gt;().HasRequired(p =&gt; p.Country); </code></pre> <p>NHibernate:</p> <pre><code>public class BaseMapping&lt;T&gt; : ClassMapping&lt;T&gt; where T : BaseEntity { public BaseMapping() { this.Lazy(true); Id(x =&gt; x.Id, map =&gt; { map.Generator(Generators.GuidComb); }); } } public class ClientMap : BaseMapping&lt;Client&gt; { public ClientMap() { this.Property(x =&gt; x.Name); this.Property(x =&gt; x.Abbreviation); this.Property(x =&gt; x.ClientSinceDate, map =&gt; map.NotNullable(true)); this.Property(x =&gt; x.ClientUntilDate); this.Property(x =&gt; x.City); this.Property(x =&gt; x.Website); this.Bag&lt;Department&gt;(x =&gt; x.Departments, colmap =&gt; { colmap.Key(x =&gt; x.Column("ClientId")); colmap.Inverse(true); colmap.Cascade(Cascade.All | Cascade.DeleteOrphans); }, map =&gt; { map.OneToMany(); }); this.Bag&lt;ClientCountry&gt;(x =&gt; x.ClientCountries, colmap =&gt; { colmap.Cascade(Cascade.All | Cascade.DeleteOrphans); colmap.Key(p =&gt; p.Column("ClientId")); colmap.Inverse(true); }, map =&gt; { map.OneToMany(); }); this.Bag&lt;Contact&gt;(x =&gt; x.Contacts, colmap =&gt; { colmap.Key(x =&gt; x.Column("ClientId")); colmap.Cascade(Cascade.All | Cascade.DeleteOrphans); }, map =&gt; { map.OneToMany(); }); } } public class CountryMap : BusinessRefEntityMapping&lt;Country&gt; { public CountryMap() { Bag&lt;ClientCountry&gt;(x =&gt; x.ClientCountries, colmap =&gt; { colmap.Cascade(Cascade.All); colmap.Key(p =&gt; p.Column("CountryId")); }, map =&gt; { map.OneToMany(); }); } } public class ClientCountryMap : BaseMapping&lt;ClientCountry&gt; { public ClientCountryMap() { Property(x =&gt; x.ValidFrom); Property(x =&gt; x.ValidTo); Property(x =&gt; x.ClientId, map =&gt; { map.Column("ClientId"); map.Insert(false); map.Update(false); map.NotNullable(true); }); Property(x =&gt; x.CountryId, map =&gt; { map.Column("CountryId"); map.Insert(false); map.Update(false); map.NotNullable(true); }); ManyToOne&lt;Client&gt;(x =&gt; x.Client, map =&gt; { map.Column("ClientId"); map.Cascade(Cascade.All); map.Insert(true); map.Update(true); map.NotNullable(true); }); ManyToOne&lt;Country&gt;(x =&gt; x.Country, map =&gt; { map.Column("CountryId"); map.Cascade(Cascade.All); map.Insert(true); map.Update(true); map.NotNullable(true); }); } } </code></pre> <p>The js code:</p> <pre><code> $scope.create = function (index) { var c = $scope.clients[index]; var newClientCountry = breezeService.manager.createEntity('ClientCountry', { ValidFrom: Date(2013, 01, 01), ValidTo: Date(2015, 01, 01), Client: c, Country: country, }); breezeService.manager.saveChanges() .then(function (data) { $log.info('client created'); }) .fail(function (dat) { $log.error('save client failed:' + data) }) } </code></pre> <p>The issue: With NHibernate, saving a clientcountry results in this error message :"not-null property references a null or transient value CdT.EAI.DAL.ClientCountry.Country". With EF, all works as expected. </p> <p>Is there something wrong with my code? </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload