%Oracle DAC/Client%\product\11.2.0\client_1\Network\Admin\tnsnames.ora
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = orasrvxp)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)
public class Employee
{
public virtual int Id { get ; private set ; }
public virtual string FirstName { get ; set ; }
public virtual string LastName { get ; set ; }
public virtual Store Store { get ; set ; }
}
* This source code was highlighted with Source Code Highlighter .
Id
property and list (one-to-many) properties are declared with the private setter. Only NHibernate will set the values ​​for Id
(through reflection), and we initialize the lists in the constructor.virtual
modifier, since NHibernate will create proxy classes for our entities, and you must enable property overloading.public class Product
{
public virtual int Id { get ; private set ; }
public virtual string Name { get ; set ; }
public virtual double Price { get ; set ; }
public virtual IList<Store> StoresStockedIn { get ; private set ; }
public Product()
{
StoresStockedIn = new List <Store>();
}
}
* This source code was highlighted with Source Code Highlighter .
public class Store
{
public virtual int Id { get ; private set ; }
public virtual string Name { get ; set ; }
public virtual IList<Product> Products { get ; private set ; }
public virtual IList<Employee> Staff { get ; private set ; }
public Store()
{
Products = new List <Product>();
Staff = new List <Employee>();
}
public virtual void AddProduct(Product product)
{
product.StoresStockedIn.Add( this );
Products.Add(product);
}
public virtual void AddEmployee(Employee employee)
{
employee.Store = this ;
Staff.Add(employee);
}
}
* This source code was highlighted with Source Code Highlighter .
Employee
class.using FluentExample.Entities;
using FluentNHibernate.Mapping;
namespace FluentExample.Mappings
{
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
}
}
}
* This source code was highlighted with Source Code Highlighter .
ClassMap
from the FluentNHibernate library. In order for Fluent NHibernate to find mappings, it is necessary to declare classes with the public
modifier. Immediately consider the full mapping:public EmployeeMap()
{
Table( "Employee" );
Id(e => e.Id)
.GeneratedBy.Sequence( "Employee_seq" );
Map(e => e.FirstName);
Map(e => e.LastName);
References(e => e.Store);
}
* This source code was highlighted with Source Code Highlighter .
Table()
, is responsible for the name of the table that is being mapped. Below we will see why you specify the name explicitly.Id()
method, we specify which field identifies the object (NHibernate: <id>
). If we used an auto-increment database, Fluent NHibernate would automatically recognize the type and assign the identity generator (NHibernate: <generator>
). But, since there is no auto-increment in Oracle, we will use sequences (sequence), which is indicated later in the method chain.<property>
), where the type and name are determined automatically. This is implemented using the property naming convention. The column name can also be specified manually using the Column()
method, but I still recommend using the default conventions or setting your own. Read more about agreements .Store
class in the singular, that is, it implements the “many” side in relation to many-to-one. The name of the foreign key, again, following the conventions, is assumed to be Store_id. The foreign key column can be overridden by the Column()
method. The References()
method is used on the “many” side, on the other side of the relationship (“one”), the HasMany()
method (NHibernate: <bag>
) will be applied, and the corresponding method of renaming the key field will be KeyColumn()
.Table()
method. The point here is that Fluent NHibernate defaults to quoting table names when displaying table names (this is the agreement), that is, our table now should have the name ”Employee”, along with quotes. In Oracle, case-only names are surrounded by quotes. In our example, I would not like to use quotes and leave the table names case-insensitive and without quotes, so I indicated them explicitly.public class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Table( "Store" );
Id(x => x.Id)
.GeneratedBy.Sequence( "Store_seq" );
Map(x => x.Name);
HasMany(x => x.Staff)
.Inverse()
.Cascade.All();
HasManyToMany(x => x.Products)
.Cascade.All()
.Table( "StoreProduct" );
}
}
* This source code was highlighted with Source Code Highlighter .
HasMany()
for the Employee
class, which we discussed above. It also uses the HasManyToMany()
method, which implements the many-to-many relationship between the store and the product through an intermediate table, whose name is specified in the chain by the Table()
method.Inverse()
method shows that the collection owner is the other end of the relationship, that is, the Employee
class, and it will be saved first. Cascade.All()
transfers events to related elements. That is, if we, for example, delete a store, then all links with products and all the staff of this store will also be deleted. For more information, see the NHibernate documentation.public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Table( "Product" );
Id(x => x.Id)
.GeneratedBy.Sequence( "Product_seq" );
Map(x => x.Name);
Map(x => x.Price);
HasManyToMany(x => x.StoresStockedIn)
.Cascade.All()
.Inverse()
.Table( "StoreProduct" );
}
}
* This source code was highlighted with Source Code Highlighter .
Copy Source | Copy HTML
- <? xml version = "1.0" encoding = "utf-8" ? >
- < configuration >
- < connectionStrings >
- < add name = "Oracle"
- connectionString = "DATA SOURCE = orcl; PASSWORD = nhibernate; PERSIST SECURITY INFO = True; USER ID = fluent"
- providerName = "Oracle.DataAccess.Client" />
- </ connectionStrings >
- </ configuration >
Oracle.DataAccess
assembly that comes with your chosen provider:Copy Local = True
, this indicates that this library should be copied to the folder with the output binary files of our project:using FluentExample.Entities;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Driver;
namespace FluentExample
{
public static class FluentNHibernateHelper
{
private static ISessionFactory _sessionFactory;
public static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null )
{
var dbConfig = OracleDataClientConfiguration.Oracle10
.ConnectionString(c => c.FromConnectionStringWithKey( "Oracle" ))
.Driver<OracleDataClientDriver>()
.ShowSql();
_sessionFactory = Fluently.Configure()
.Database(dbConfig)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Employee>())
.BuildSessionFactory();
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
}
* This source code was highlighted with Source Code Highlighter .
OracleDataClientConfiguration
predefined class from the OracleDataClientConfiguration
namespace and configure it to use the connection string we created and the NHibernate driver. You can also enable the option to display the generated SQL queries. Learn more about database configuration .class Program
{
static void Main()
{
using (FluentNHibernateHelper.OpenSession())
{
}
}
}
* This source code was highlighted with Source Code Highlighter .
private static void Main()
{
using ( var session = FluentNHibernateHelper.OpenSession())
{
using ( var transaction = session.BeginTransaction())
{
var barginBasin = new Store { Name = "Bargin Basin" };
var superMart = new Store { Name = "SuperMart" };
var potatoes = new Product { Name = "Potatoes" , Price = 3.60 };
var fish = new Product { Name = "Fish" , Price = 4.49 };
var milk = new Product { Name = "Milk" , Price = 0.79 };
var bread = new Product { Name = "Bread" , Price = 1.29 };
var cheese = new Product { Name = "Cheese" , Price = 2.10 };
var waffles = new Product { Name = "Waffles" , Price = 2.41 };
var daisy = new Employee { FirstName = "Daisy" , LastName = "Harrison" };
var jack = new Employee { FirstName = "Jack" , LastName = "Torrance" };
var sue = new Employee { FirstName = "Sue" , LastName = "Walkters" };
var bill = new Employee { FirstName = "Bill" , LastName = "Taft" };
var joan = new Employee { FirstName = "Joan" , LastName = "Pope" };
// . ,
// many-to-many.
AddProductsToStore(barginBasin, potatoes, fish, milk, bread, cheese);
AddProductsToStore(superMart, bread, cheese, waffles);
//
AddEmployeesToStore(barginBasin, daisy, jack, sue);
AddEmployeesToStore(superMart, bill, joan);
//
session.SaveOrUpdate(barginBasin);
session.SaveOrUpdate(superMart);
transaction.Commit();
}
//
using (session.BeginTransaction())
{
var stores = session.CreateCriteria( typeof (Store)). List <Store>();
foreach ( var store in stores)
WriteStorePretty(store);
}
Console .ReadKey();
}
}
public static void AddProductsToStore(Store store, params Product[] products)
{
foreach ( var product in products)
store.AddProduct(product);
}
public static void AddEmployeesToStore(Store store, params Employee[] employees)
{
foreach ( var employee in employees)
store.AddEmployee(employee);
}
private static void WriteStorePretty(Store store)
{
Console .WriteLine(store.Name);
Console .WriteLine( " Products:" );
foreach ( var product in store.Products)
Console .WriteLine( " " + product.Name);
Console .WriteLine( " Staff:" );
foreach ( var employee in store.Staff)
Console .WriteLine( " " + employee.FirstName + " " + employee.LastName);
Console .WriteLine();
}
* This source code was highlighted with Source Code Highlighter .
<sql-insert>
.Source: https://habr.com/ru/post/125135/
All Articles