Association mapping in Fluent NHibernate
This article explains and illustrates on a practical example, how the support of different association mapping is implemented in Entity Developer with Fluent NHibernate.
This article also contains samples of mapping for the following associations:
One-To-Many Associations:
NHibernate provides several ways for collection mappings:
- Set;
- Bag;
- List;
- Map(Dictionary);
- Array.
Within the database, a one-to-many mapping is arranged as a table with a primary key for the one side of the mapping and another table that contains a field, which references the primary key of the first table.
There can be a collection of items with no key that would allow retrieving them from the collection. In the collection, all elements can be defined as unique (a Set) or, alternatively, they can be duplicated (a Bag).
It is also possible to arrange a collection of items with a key that allows retrieving those items from the collection. This key can be either an integer (a List) or another simple type, or even an object (in this case, it is called a Dictionary).
Set and Map Types of Collection Mapping Sample:
The database contains the Dept and Emp tables, which have a foreign key constraint between them.
The field DEPTNO in the table Emp receives the id value of the associated record in the Dept table.
We perform the following sequence of operations: create an NHibernate model, add the Dept and Emp tables to the model, add the additional Fluent NHibernate template to generate fluent mapping. In the result we have the following model:
If the navigation property Emps is defined as Set, then the generated fluent mapping for the model will be as follows:
public class EmpMap : ClassMap<Emp>
{
public EmpMap()
{
Schema("dbo");
Table("Emp");
LazyLoad();
Id(x => x.EMPNO)
.Column("EMPNO")
.CustomType("Int32")
.Access.Property()
.CustomSqlType("int")
.Not.Nullable()
.Precision(10)
.GeneratedBy.Assigned();
Map(x => x.ENAME)
.Column("ENAME")
.CustomType("String")
.Access.Property()
.Generated.Never()
.CustomSqlType("varchar")
.Length(10);
Map(x => x.JOB)
.Column("JOB")
.CustomType("String")
.Access.Property()
.Generated.Never()
.CustomSqlType("varchar")
.Length(9);
Map(x => x.MGR)
.Column("MGR")
.CustomType("Int32")
.Access.Property()
.Generated.Never()
.CustomSqlType("int")
.Precision(10);
Map(x => x.HIREDATE)
.Column("HIREDATE")
.CustomType("DateTime")
.Access.Property()
.Generated.Never()
.CustomSqlType("datetime");
Map(x => x.SAL)
.Column("SAL")
.CustomType("Double")
.Access.Property()
.Generated.Never()
.CustomSqlType("float")
.Precision(53);
Map(x => x.COMM)
.Column("COMM")
.CustomType("Double")
.Access.Property()
.Generated.Never()
.CustomSqlType("float")
.Precision(53);
References(x => x.Dept)
.Class<Dept>()
.Access.Property()
.Cascade.None()
.LazyLoad()
.Columns("DEPTNO");
}
}
public class DeptMap : ClassMap<Dept>
{
public DeptMap()
{
Schema("dbo");
Table("Dept");
LazyLoad();
Id(x => x.DEPTNO)
.Column("DEPTNO")
.CustomType("Int32")
.Access.Property()
.CustomSqlType("int")
.Not.Nullable()
.Precision(10)
.GeneratedBy.Assigned();
Map(x => x.DNAME)
.Column("DNAME")
.CustomType("String")
.Access.Property()
.Generated.Never()
.CustomSqlType("varchar")
.Length(14);
Map(x => x.LOC)
.Column("LOC")
.CustomType("String")
.Access.Property()
.Generated.Never()
.CustomSqlType("varchar")
.Length(13);
HasMany<Emp>(x => x.Emps)
.Access.Property()
// for the Bag collection mapping, we need to call AsBag()
.AsSet() // for the Set collection mapping, we call AsSet()
.Cascade.None()
.LazyLoad()
.Inverse()
.KeyColumns.Add("DEPTNO", mapping => mapping.Name("DEPTNO")
.SqlType("int")
.Nullable());
}
}
The code above represents the generated model mapping classes. The mapping of each class contains the descriptions of the identity key mapping and class properties, as well as the definitions of the name of the table in the database, the name of the schema, to which the table belongs. In the mapping of the Emp class the References function is used to create a reference to the master entity Dept. In database terms, this is a many-to-one relationship; while the Columns function specifies the name of the details table(Emp) column, against which the foreign key is created in the database together with the master table(Dept). In the mapping of the Dept class the HasMany function is used to map a collection of entities as a one-to-many association, the call of AsSet() indicates that the collection is mapped as a Set; while the KeyColumns.Add function specifies the name of the details table(Emp) column, against which the foreign key is created in the database together with the master table(Dept), its type and other mapping parameters.
On the other hand, if the collection type of the navigation property is set to Bag, than the generated fluent mapping for this model will be the same as shown above, except that when the HasMany function is used to map the collection of entities as a one-to-many, the AsBag() function will be called instead of the AsSet() function to indicate that the collection is mapped as a Bag. All the other aspects of the mapping will be identical.
Map(Dictionary) type of collection mapping sample:
In this example, we shall use the tables from the previous example for Set and Bag collection mapping.
The model is created in the same way as in the previous example. After the model has been created, we need to display the Association Editor dialog. Through this dialog box, we need to set the Generate relation property of the Dept navigation property to False, since only Set or Bag may be used for the “many” end of a bidirectional association. After that, we need to set the collection type of the Emps navigation property to Map and specify the ENAME column as the Index column. Now the Employees navigation property of the class Dept is mapped as Map collection mapping and is filled with instances of the class Emp. You can find the instances by looking in the mapped table for Emp and find records with the field DEPTNO having value equal to DEPTNO field value of the table Dept. The field ENAME in the table Emp receives the key value of the entry in the dictionary. The key used in the map is of type String and can be found in the column ENAME of the table used to store the Emp objects. The type of the key used in this sample is string.
Below is the generated fluent mapping for this model:
public class DeptMap : ClassMap<Dept> { public DeptMap() { Schema("dbo"); Table("Dept"); LazyLoad(); Id(x => x.DEPTNO) .Column("DEPTNO") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Assigned(); Map(x => x.DNAME) .Column("DNAME") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("varchar") .Length(14); Map(x => x.LOC) .Column("LOC") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("varchar") .Length(13); HasMany<Emp>(x => x.Emps) .Access.Property() .AsMap<string>("ENAME") .Cascade.None() .LazyLoad() .KeyColumns.Add("DEPTNO", mapping => mapping.Name("DEPTNO") .SqlType("int") .Nullable()); } } public class EmpMap : ClassMap<Emp> { public EmpMap() { Schema("dbo"); Table("Emp"); LazyLoad(); Id(x => x.EMPNO) .Column("EMPNO") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Assigned(); Map(x => x.ENAME) .Column("ENAME") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("varchar") .Length(10); Map(x => x.JOB) .Column("JOB") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("varchar") .Length(9); Map(x => x.MGR) .Column("MGR") .CustomType("Int32") .Access.Property() .Generated.Never() .CustomSqlType("int") .Precision(10); Map(x => x.HIREDATE) .Column("HIREDATE") .CustomType("DateTime") .Access.Property() .Generated.Never() .CustomSqlType("datetime"); Map(x => x.SAL) .Column("SAL") .CustomType("Double") .Access.Property() .Generated.Never() .CustomSqlType("float") .Precision(53); Map(x => x.COMM) .Column("COMM") .CustomType("Double") .Access.Property() .Generated.Never() .CustomSqlType("float") .Precision(53); } }
The code above represents the generated model mapping classes. The mapping of each class contains the descriptions of the identity key mapping and class properties, as well as the definitions of the name of the table in the database, the name of the schema, to which the table belongs. In the mapping of the Dept class the HasMany function is used to map a collection of entities as a one-to-many, the call of AsMap<string>("ENAME") indicates that the collection is mapped as Map and specifies the key type and the name of the column that receives the key value of the entry in the dictionary; while the KeyColumns.Add function specifies the name of the details table(Emp) column, against which the foreign key is created in the database together with the master table(Dept), as well as its type and other mapping parameters.
List and Array types of collection mapping sample:
The database contains the Message and Conversation tables, linked though the foreign key constraint.
The field ConversationId in the Message table receives the id value of the associated record in the Conversation table. Additionally, the Message table has the Order column, whose value determines the sequence of the message in the message list of each conversation.
We perform the following sequence of operations: create an NHibernate model, add the Message and Conversation tables to the model; display the Association Editor dialog, through which we set the Generation relation property of the Conversation property to False, since only Set or Bag may be used for the “many” end of a bidirectional association. After that, we set the collection type of the Messages navigation property to List or Array, specify the Order column as the Index column, add the additional Fluent NHibernate template to generate fluent mapping. In the result, we have the following model:
If the collection type of the Emps navigation property is set to List, then the generated fluent mapping for this model will be as follows:
public class ConversationMap : ClassMap<Conversation> { public ConversationMap() { Schema("NHListSample"); Table("Conversation"); LazyLoad(); Id(x => x.Id) .Column("Id") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Assigned(); Map(x => x.Description) .Column("Description") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("varchar") .Length(255); Map(x => x.Date) .Column("DATE") .CustomType("DateTime") .Access.Property() .Generated.Never() .Default("getdate()") .CustomSqlType("datetime") .Not.Nullable(); HasMany<Message>(x => x.Messages) .Access.Property() // for the List collection mapping, we need to call AsList .AsList(index => index.Column("`Order`").Type<int>()) // for the Array collection mapping, we need to call AsArray // .AsArray<int>(child => child.Id, map => map.Column("`Order`").Type<int>()) .Cascade.None() .LazyLoad() // for the Array collection mapping we need to remove .KeyColumns.Add("ConversationId", mapping => mapping.Name("ConversationId") .SqlType("int") .Not.Nullable()); } } public class MessageMap : ClassMap<Message> { public MessageMap() { Schema("NHListSample"); Table("Message"); LazyLoad(); Id(x => x.Id) .Column("Id") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Identity(); Map(x => x.Order) .Column("`Order`") .CustomType("Int32") .Access.Property() .Generated.Never() .Default("'0'") .CustomSqlType("int") .Not.Nullable() .Precision(10); Map(x => x.Text) .Column("Text") .CustomType("String") .Access.Property() .Generated.Never() .Default("''") .CustomSqlType("varchar") .Not.Nullable() .Length(45); } }
The code above represents the generated model mapping classes. The mapping of each class contains the descriptions of the identity key mapping and class properties, as well as the definitions of the name of the table in the database, the name of the schema, to which the table belongs. In the mapping of the Conversation class, the HasMany function is used to map a collection of entities as a one-to-many association, and the call of AsList() indicates that the collection is mapped as List; here we also specify mapping for the index; while the KeyColumns.Add function specifies the name of the details table(Message) column, against which the foreign key is created in the database together with the master table(Conversation), its type and other mapping parameters. The index (and thus position) of the element in the list is specified by the value in the Order field of the table.
Alternatively, if the collection type of the Emps navigation property is set to Array, then the genrated fluent mapping for this model will be the same as above, however, in the mapping of the Conversation class, when the HasMany function is used to map a collection of entities as a one-to-many association, instead of calling AsList(index => index.Column("`Order`").Type<int>()) we have to call AsArray<int>(child => child.Id, map => map.Column("`Order`").Type<int>()) that sets the Array collection mapping. It should also be noted that we cannot call LazyLoad() for Array collection mapping, so we need to remove this call.
Many-To-Many Associations:
Many-to-many associations use an intermediate table that has a foreign key to the tables of both associated entities. An object uses several objects of another type, and this latter object references several objects of the first type. As is always the case for many-to-many mappings in relational databases, we need a third table which provides the cross-references for the many-to-many relationship.
The database contains the Employees, Territories tables and EmployeeTerritories table, which provides the cross-references for the many-to-many relationship.
We perform the following sequence of operations: create an NHibernate model, add the Employees, Territories, and EmployeeTerritories tables, add the additional Fluent NHibernate template to generate fluent mapping. In the result, we have the following model:
The Territories navigation property of the type Employees is a many-to-many property to a Set collection of objects with the type Territory. The values for the objects in this collection can be found by looking for entries in the table for Territory objects with an TerritoryID equal to the values in the column TerritoryID of the EmployeeTerritories table with a value of EmployeeID equal to this object's EmployeeID.
The Employees navigation property of the type Territory is a many-to-many property to a Set collection of objects with the type Employees. The values for the objects in this collection can be found by looking for entries in the table for Employees objects with an EmployeeID equal to the values in the column EmployeeID of the EmployeeTerritories table with a value of TerritoryID equal to this object's TerritoryID.
In our example, both navigation properties are mapped as a Set, although for many-to-many associations we can use any other type of collection mapping, if needed.
Below is the generated fluent mapping for this model:
public class TerritoryMap : ClassMap<Territory> { public TerritoryMap() { Schema("dbo"); Table("Territories"); LazyLoad(); Id(x => x.TerritoryID) .Column("TerritoryID") .CustomType("String") .Access.Property() .CustomSqlType("nvarchar") .Not.Nullable() .Length(20) .GeneratedBy.Assigned(); Map(x => x.TerritoryDescription) .Column("TerritoryDescription") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nchar") .Not.Nullable() .Length(50); Map(x => x.RegionID) .Column("RegionID") .CustomType("Int32") .Access.Property() .Generated.Never() .CustomSqlType("int") .Not.Nullable() .Precision(10); HasManyToMany<Employees>(x => x.Employees) .Access.Property() .AsSet() .Cascade.None() .LazyLoad() .Inverse() .Schema("dbo") .Table("EmployeeTerritories") .FetchType.Join() .ChildKeyColumns.Add("EmployeeID", mapping => mapping.Name("EmployeeID") .SqlType("int") .Not.Nullable()) .ParentKeyColumns.Add("TerritoryID", mapping => mapping.Name("TerritoryID") .SqlType("nvarchar") .Not.Nullable() .Length(20)); } } public class EmployeesMap : ClassMap<Employees> { public EmployeesMap() { Schema("dbo"); Table("Employees"); LazyLoad(); Id(x => x.EmployeeID) .Column("EmployeeID") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Identity(); Map(x => x.LastName) .Column("LastName") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(20); Map(x => x.FirstName) .Column("FirstName") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(10); Map(x => x.Title) .Column("Title") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(30); Map(x => x.TitleOfCourtesy) .Column("TitleOfCourtesy") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(25); Map(x => x.BirthDate) .Column("BirthDate") .CustomType("DateTime") .Access.Property() .Generated.Never() .CustomSqlType("datetime"); Map(x => x.HireDate) .Column("HireDate") .CustomType("DateTime") .Access.Property() .Generated.Never() .CustomSqlType("datetime"); Map(x => x.Address) .Column("Address") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(60); Map(x => x.City) .Column("City") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(15); Map(x => x.Region) .Column("Region") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(15); Map(x => x.PostalCode) .Column("PostalCode") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(10); Map(x => x.Country) .Column("Country") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(15); Map(x => x.HomePhone) .Column("HomePhone") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(24); Map(x => x.Extension) .Column("Extension") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(4); Map(x => x.Photo) .Column("Photo") .CustomType("BinaryBlob") .Access.Property() .Generated.Never() .CustomSqlType("image") .Length(2147483647); Map(x => x.Notes) .Column("Notes") .CustomType("StringClob") .Access.Property() .Generated.Never() .CustomSqlType("ntext") .Length(1073741823); Map(x => x.ReportsTo) .Column("ReportsTo") .CustomType("Int32") .Access.Property() .Generated.Never() .CustomSqlType("int") .Precision(10); Map(x => x.PhotoPath) .Column("PhotoPath") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(255); HasManyToMany<Territory>(x => x.Territories) .Access.Property() .AsSet() .Cascade.None() .LazyLoad() .Schema("dbo") .Table("EmployeeTerritories") .FetchType.Join() .ChildKeyColumns.Add("TerritoryID", mapping => mapping.Name("TerritoryID") .SqlType("nvarchar") .Not.Nullable() .Length(20)) .ParentKeyColumns.Add("EmployeeID", mapping => mapping.Name("EmployeeID") .SqlType("int") .Not.Nullable()); } }
The code above represents the generated model mapping classes. The mapping of each class contains the the descriptions of the identity key mapping and class properties, as well as the definitions of the name of the table in the database, the name of the schema, to which the table belongs. Additionally, in the mapping of the classes, the HasManyToMany function is used to set up the mapping for the navigation property of the many-to-many association: we need to specify the type of collection mapping, the name of the link table in the database, which provides the cross-references for the many-to-many relationship, the name of the schema, to which the table belongs; we also need to specify the mapping for columns of the (EmployeeTerritories) link table, which will provide cross-references for the many-to-many relationship between the associated tables (Employees and Territories).
One-To-One Associations:
One-to-one associations are the simplest kind of associations. They usually correspond to the foreign key relations when the foreign key column is the primary key column.
The following two cases are possible, when we map a one-to-one association:
Case 1. When the foreign key and the primary key in the dependent entity class (class, corresponding to the table that has the foreign key) consist of the same columns.
The database contains the Person and Contact tables, between which there is a foreign key created against the primary key fields of these tables.
We perform the following sequence of operations: create an NHibernate model, add the Person and Contact tables to the model, add the additional Fluent NHibernate template to generate fluent mapping. In the result we have the following model:
Below is the generated fluent mapping for this model:
public class ContactMap : ClassMap<Contact> { public ContactMap() { Schema("dbo"); Table("Contact"); LazyLoad(); Id(x => x.ContactID) .Column("ContactID") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Assigned(); Map(x => x.FirstName) .Column("FirstName") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(50); Map(x => x.LastName) .Column("LastName") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(50); Map(x => x.Email) .Column("Email") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(50); Map(x => x.Phone) .Column("Phone") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nchar") .Length(13); HasOne(x => x.Person) .Class<Person>() .Access.Property() .Cascade.None() .LazyLoad(); } } public class PersonMap : ClassMap<Person> { public PersonMap() { Schema("dbo"); Table("Person"); LazyLoad(); Id(x => x.PersonID) .Column("PersonID") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Assigned(); Map(x => x.BirthDay) .Column("BirthDay") .CustomType("DateTime") .Access.Property() .Generated.Never() .CustomSqlType("datetime") .Not.Nullable(); Map(x => x.ADDRESS) .Column("ADDRESS") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(200); HasOne(x => x.Contact) .Class<Contact>() .Access.Property() .Cascade.None() .LazyLoad() // indicates that the (Person) table that corresponds to the type has a foreign key .Constrained(); } }
The code above represents the generated model mapping classes. The mapping of each class contains the descriptions of the identity key mapping and class properties, as well as the definitions of the name of the table in the database, the name of the schema, to which the table belongs. Additionally, in the mapping of the classes the HasOne function is used to set up the mapping of the navigation property of the one-to-one association: it specifies the class, which the navigation property refers to, its access and other mapping settings, while the call of the Constrained() in this definition indicates that the (Person) table, corresponding to this type, has the foreign key.
Case 2. When foreign key is some non-primary unique property. You need to specify the foreign key column of the constrained table in this case.
The database contains the Person and Contact tables, between which there is a foreign key that is created against the ContactID primary key field of the Contact table and the ContactID unique field of the Person table.
We perform the following sequence of operations: create an NHibernate model, add the Person and Contact tables to the model; display the Association Editor dialog and set the Separate Fioreign Key parameter of the Contact property to True as well as set the Foreign Key column to the ContactID column, and, finally, add the additional Fluent NHibernate template to generate fluent mapping. In the result we have the following model:
Below is the generated fluent mapping for this model:
public class ContactMap : ClassMap<Contact> { public ContactMap() { Schema("OneToOneSeparateFK"); Table("Contact"); LazyLoad(); Id(x => x.ContactID) .Column("ContactID") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Assigned(); Map(x => x.FirstName) .Column("FirstName") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(50); Map(x => x.LastName) .Column("LastName") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(50); Map(x => x.Email) .Column("Email") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Length(50); Map(x => x.Phone) .Column("Phone") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nchar") .Length(13); HasOne(x => x.Person) .Class<Person>() .Access.Property() .Cascade.None() .LazyLoad() // Sets the property reference .PropertyRef(p => p.Contact); } } public class PersonMap : ClassMap<Person> { public PersonMap() { Schema("OneToOneSeparateFK"); Table("Person"); LazyLoad(); Id(x => x.PersonID) .Column("PersonID") .CustomType("Int32") .Access.Property() .CustomSqlType("int") .Not.Nullable() .Precision(10) .GeneratedBy.Assigned(); Map(x => x.BirthDay) .Column("BirthDay") .CustomType("DateTime") .Access.Property() .Generated.Never() .CustomSqlType("datetime") .Not.Nullable(); Map(x => x.ADDRESS) .Column("ADDRESS") .CustomType("String") .Access.Property() .Generated.Never() .CustomSqlType("nvarchar") .Not.Nullable() .Length(200); References(x => x.Contact) .Class<Contact>() .Access.Property() .Cascade.None() .LazyLoad() // specifies the column used in this relationship .Columns("ContactID"); } }
The code above represents the generated model mapping classes. The mapping of each class contains the descriptions of the identity key mapping and class properties, as well as the definitions of the name of the table in the database, the name of the schema, to which the table belongs. In the mapping of the Contact class, the HasOne function is used to set up mapping of the Person navigation property of the one-to-one association: the function specifies the class the navigation property references, navigation property access, and other settings of the mapping. In the mapping of the Person class, the References function is used to set up the mapping of the Contact navigation property of the one-to-one association: it specifies the class the navigation property references, specifies the ContactID field of the Person table, against which the foreign key with the Contact table is created, navigation property access and other settings of the mapping.
Post Comment
Наша компания предлагает куплю сетку тканую производства Северсталь метиз ОСПАЗ со склада
г.Орел. В наличии огромный ассортиментсетка тканая фильтровая.
Вы можете купить тканая сетка магазин светлую и оцинкованную.
У нас всегда в наличии огромный выбор тканая сетка в розницу, цены от производителя.
Продажа интернет магазин тканей сетка оптом и в розницу со склада г.Орел.Ia??a?аАааАТаЂ ve read some good stuff here. Definitely price bookmarking for revisiting. I surprise how so much effort you place to make this sort of magnificent informative website.
My brother suggested I may like this website. He used to be totally right.
Major thankies for the article.Much thanks again. Will read on
We stumbled over here from a different web address and thought I may as well check things out. I like what I see so now i am following you. Look forward to finding out about your web page yet again.
Way cool! Some extremely valid points! I appreciate you writing this write-up and the rest of the website is really good.
There is definately a great deal to know about this subject. I love all of the points you ave made.
I truly like your weblog put up. Preserve publishing a lot more beneficial data, we recognize it!
site is something that as needed on the web, someone with a little originality!
Very good blog article.Thanks Again. Keep writing.
Thank you for sharing this great article. Very inspiring! (as always, btw)
Major thankies for the blog.Much thanks again. Really Great.
Very good post.Really thank you! Really Cool.
Your style is very unique in comparison to other people I have read stuff from. Many thanks for posting when you have the opportunity, Guess I will just bookmark this site.
There is visibly a bunch to realize about this. I believe you made certain nice points in features also.
Way cool! Some extremely valid points! I appreciate you writing this write-up and also the rest of the site is also very good.
I really liked your article post.Really thank you! Much obliged.
Of course, what a fantastic site and informative posts, I definitely will bookmark your site.Have an awsome day!
Very good info. Lucky me I came across your website by accident (stumbleupon). I have book-marked it for later!
If you ever want to take some of the load off, I ad love to write some content for your blog in exchange for
The league as new contract with the womens peyton manning jersey; they can
This is one awesome blog post.Thanks Again. Want more.
Im thankful for the article.Thanks Again. Great.
This text is worth everyone as attention. Where can I find out more?
Well I truly enjoyed studying it. This article provided by you is very useful for good planning.
Q8FSPO You, my pal, ROCK! I found exactly the information I already searched all over the place and just could not locate it. What a perfect web-site.
Some times its a pain in the ass to read what blog owners wrote but this web site is real user genial !.
Wow, great blog article.Really thank you! Will read on
Way cool! Some very valid points! I appreciate you writing this write-up and also the rest of the website is also very good.
Really informative article post.Much thanks again. Great.
Very good blog post.Thanks Again. Keep writing.
Really enjoyed this article. Will read on
Well I sincerely enjoyed reading it. This tip procured by you is very helpful for accurate planning.
Really informative blog post.Much thanks again. Really Great.
I think other site proprietors should take this website as an model, very clean and wonderful user genial style and design, as well as the content. You are an expert in this topic!
Really informative blog article.Really thank you! Will read on
Rattling fantastic information can be found on weblog. I believe in nothing, everything is sacred. I believe in everything, nothing is sacred. by Tom Robbins.
Thank you ever so for you blog.Really looking forward to read more. Awesome.
Wow! This can be one particular of the most helpful blogs We ave ever arrive across on this subject. Basically Fantastic. I am also an expert in this topic so I can understand your effort.
Nothing more nothing less. The whole truth about the reality around us.
that it can easily likewise remedy additional eye mark complications to ensure you can certainly get one
Wow, great blog post.Really looking forward to read more. Will read on
pretty handy stuff, overall I think this is worthy of a bookmark, thanks
You made some decent points there. I did a search on the issue and found most individuals will agree with your website.
I will right away grab your rss as I can not find your email subscription link or newsletter service. Do you ave any? Please let me know in order that I could subscribe. Thanks.
Very interesting points you have mentioned, regards for putting up.
Travel view of Three Gorges | Wonder Travel Blog
I truly appreciate this blog article.Thanks Again. Cool.
I went over this site and I believe you have a lot of great information, saved to my bookmarks (:.
Pretty! This has been an extremely wonderful post. Thank you for supplying this information.