Fluent NHibernate হল NHibernate ORM এর জন্য একটি শক্তিশালী টুল যা কোড-বেসড ম্যাপিংয়ের মাধ্যমে ডেটাবেসের সাথে অবজেক্ট সম্পর্ক (Object-Relational Mapping) তৈরি করতে সহায়তা করে। Fluent NHibernate-এর মাধ্যমে, আপনি ক্লাসগুলোর জন্য ম্যানুয়াল XML ফাইল এড়িয়ে সোজাসুজি কোডিংয়ের মাধ্যমে ম্যাপিং করতে পারেন। এতে কাস্টমাইজেশনও অনেক সহজ হয়ে যায়।
এখানে আমরা Fluent NHibernate ব্যবহার করে কিভাবে কাস্টম ম্যাপিং করা যায়, এবং কিভাবে বিভিন্ন মাপিং কাস্টমাইজেশন (যেমন: কাস্টম টাইপ, কাস্টম কলাম, লকিং পদ্ধতি ইত্যাদি) করা যায়, সে সম্পর্কে আলোচনা করব।
Fluent NHibernate এর মাধ্যমে Mapping Customization
Fluent NHibernate আপনাকে বিভিন্ন ধরনের Customization করার সুবিধা দেয় যেমন:
- Column Names পরিবর্তন
- Custom Data Types ব্যবহার
- Relationships Mapping
- Cascading and Locking Customization
- Indexing and Constraints Customization
Column Names Customization
Column Names কাস্টমাইজ করা খুবই সাধারণ একটি কাস্টমাইজেশন। কখনও কখনও আপনার ডেটাবেসে টেবিল বা কলামের নাম অন্যরকম হতে পারে, এবং আপনাকে এই নামগুলোকে আপনার ক্লাস প্রপার্টির সাথে ম্যাপ করতে হতে পারে।
উদাহরণ:
ধরা যাক, আমাদের Employee ক্লাসের EmployeeId প্রপার্টি ডেটাবেসে EmpId নামে সেভ করা হবে। এর জন্য Fluent NHibernate এর মাধ্যমে কলাম নাম কাস্টমাইজ করা যায়।
public class Employee
{
public virtual int EmployeeId { get; set; }
public virtual string Name { get; set; }
public virtual int Age { get; set; }
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Table("Employees");
Id(x => x.EmployeeId).Column("EmpId"); // Map EmployeeId to EmpId column
Map(x => x.Name).Length(100).Not.Nullable();
Map(x => x.Age).Not.Nullable();
}
}
এখানে:
- Id(x => x.EmployeeId).Column("EmpId"):
EmployeeIdপ্রপার্টি ডেটাবেসেEmpIdনামে সেভ হবে।
Custom Data Types
কখনও কখনও, আপনার ডেটাবেসে কোন প্রপার্টি এমন ধরনের ডেটা ধারণ করতে পারে যা স্ট্যান্ডার্ড ডেটা টাইপের বাইরে। এর জন্য আপনি কাস্টম টাইপ ব্যবহার করতে পারেন।
উদাহরণ:
ধরা যাক, আমাদের একটি Employee ক্লাসের Salary প্রপার্টি আছে যা ডেটাবেসে ডেসিমাল টাইপ হিসাবে সেভ করা হবে, তবে আমাদের এটা কাস্টম টাইপ হিসেবে এনকোড করতে হবে।
public class Employee
{
public virtual int EmployeeId { get; set; }
public virtual string Name { get; set; }
public virtual decimal Salary { get; set; }
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Table("Employees");
Id(x => x.EmployeeId).GeneratedBy.Identity();
Map(x => x.Name).Length(100).Not.Nullable();
Map(x => x.Salary).CustomType<CustomDecimalType>(); // Custom data type
}
}
এখানে:
- CustomType(): এটি
Salaryপ্রপার্টির জন্য একটি কাস্টম ডেটা টাইপ ব্যবহার করছে, যা আপনার নিজস্ব লজিক বা এনকোডিং স্ট্রাটেজি প্রয়োগ করতে পারে।
আপনার CustomDecimalType ক্লাসের উদাহরণ:
public class CustomDecimalType : IType
{
public string Name => "custom_decimal";
public object Get(object value)
{
// Custom logic for retrieving decimal value
return (decimal)value;
}
public void Set(object value)
{
// Custom logic for setting decimal value
}
}
Relationships Mapping
Fluent NHibernate আপনাকে One-to-Many, Many-to-Many, এবং Many-to-One সম্পর্কগুলি ম্যাপ করতে সাহায্য করে। এই সম্পর্কগুলো কাস্টমাইজ করার জন্য আপনি Cascade অপশন, Inverse সম্পর্ক এবং Foreign Key কাস্টমাইজেশন ব্যবহার করতে পারেন।
One-to-Many Example:
public class Department
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Employee> Employees { get; set; }
public Department()
{
Employees = new List<Employee>();
}
}
public class DepartmentMap : ClassMap<Department>
{
public DepartmentMap()
{
Table("Departments");
Id(x => x.Id);
Map(x => x.Name);
// One-to-Many relationship
HasMany(x => x.Employees)
.Cascade.All()
.Inverse()
.KeyColumn("DepartmentId"); // Foreign key in Employee table
}
}
এখানে:
- HasMany(x => x.Employees): এটি Department এবং Employee এর মধ্যে একের বিপরীতে একাধিক সম্পর্ক তৈরি করছে।
- Cascade.All(): এর মাধ্যমে সমস্ত পরিবর্তন (save, update, delete) Employee টেবিলেও প্রভাব ফেলবে।
- Inverse(): এটি চিহ্নিত করে যে Employee টেবিলের মধ্যে সম্পর্কের ইনভার্স সাইড রয়েছে।
- KeyColumn("DepartmentId"): এটি বিদেশী কী (Foreign Key) নির্দেশ করে যা Employee টেবিলের মধ্যে থাকবে।
Cascading and Locking Customization
Fluent NHibernate আপনাকে বিভিন্ন ধরনের Cascading এবং Locking কাস্টমাইজেশন করতে দেয়। Cascading সম্পর্কিত অপারেশন (যেমন: save, update, delete) অন্য টেবিলগুলোতে স্বয়ংক্রিয়ভাবে প্রভাব ফেলে।
Cascade Example:
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Table("Employees");
Id(x => x.EmployeeId);
Map(x => x.Name).Length(100).Not.Nullable();
// One-to-Many relationship with cascade
HasMany(x => x.Projects)
.Cascade.SaveUpdate(); // Cascade save and update
}
}
এখানে:
- Cascade.SaveUpdate(): এটি নিশ্চিত করে যে যখন
Employeeআপডেট বা সেভ হবে, তখন তার সম্পর্কিত Projects টেবিলেও পরিবর্তন হবে।
Locking Example:
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Table("Employees");
Id(x => x.EmployeeId);
Map(x => x.Name).Length(100).Not.Nullable();
// Locking customizations
OptimisticLock.IsVersion(); // Enables Optimistic Locking with versioning
}
}
এখানে:
- OptimisticLock.IsVersion(): এটি Optimistic Locking সক্ষম করে, যার মাধ্যমে ডেটার ভার্সনিং সিস্টেম ব্যবহার করা হয় যাতে কনকারেন্সি কনফ্লিক্ট হয় না।
Conclusion
Fluent NHibernate এর মাধ্যমে Mapping Customization খুবই শক্তিশালী এবং নমনীয়। এটি আপনাকে ক্লাসের প্রপার্টি এবং ডেটাবেস টেবিলের মধ্যে ম্যাপিং করতে সাহায্য করে, এবং বিভিন্ন কাস্টমাইজেশন অপশন যেমন Column Names, Custom Data Types, Relationships, Cascading, এবং Locking ইত্যাদি ব্যবহার করে আরও উন্নত কনফিগারেশন করা সম্ভব। Fluent NHibernate এর মাধ্যমে ম্যাপিং আরও সুস্পষ্ট এবং কমপ্লেক্স অ্যাপ্লিকেশনে ডেটাবেস সম্পর্ক বজায় রাখা সহজ হয়।
Fluent NHibernate হল NHibernate-এর জন্য একটি ফ্লুয়েন্ট API যা আপনাকে একটি এলিগেন্ট এবং কাস্টমাইজেবল উপায়ে NHibernate-এর কনফিগারেশন এবং মডেল ম্যাপিং করতে সহায়তা করে। এটি XML-based কনফিগারেশন ফাইলের পরিবর্তে কোড-বেসড কনফিগারেশন ব্যবহারের মাধ্যমে NHibernate ম্যাপিং আরও সহজ এবং পাঠযোগ্য করে তোলে। Fluent NHibernate ব্যবহার করলে ডেটাবেস মডেল এবং প্রোপার্টি ম্যাপিং কনফিগারেশন সহজে লেখা যায় এবং এটি দ্রুত ডেভেলপমেন্ট প্রক্রিয়ায় সহায়তা করে।
Fluent NHibernate এর সুবিধাসমূহ
- সহজ এবং পরিষ্কার কোড: XML কনফিগারেশনের তুলনায় কোড-ভিত্তিক কনফিগারেশন আরও পরিষ্কার এবং সহজ বুঝতে।
- কমপ্লেক্স মডেল ম্যাপিং: জটিল মডেল ম্যাপিং সহজে করা যায়, যেমন ইনহেরিটেন্স, কাস্টম টাইপ, এবং ক্যাশিং কনফিগারেশন।
- নিরাপত্তা: টাইপ-সেফ কোড লেখার সুযোগ দিয়ে, এটি কোডের ভুল হওয়া কমিয়ে আনে এবং রানের সময় ত্রুটি কম করে।
- উন্নত কনফিগারেশন: হাই-লেভেল কনফিগারেশন যেমন ক্যাশিং, কাস্টম টাইপ, এবং অন্যান্য এনহাইবারনেট অপশনগুলির জন্য আরও অপশন প্রোভাইড করে।
Fluent NHibernate ব্যবহার শুরু করা
Fluent NHibernate ব্যবহার করতে হলে প্রথমে কিছু নির্দিষ্ট প্যাকেজ ইনস্টল করতে হবে। নিচে ধাপগুলো দেওয়া হলো:
1. NuGet প্যাকেজ ইনস্টলেশন
Fluent NHibernate ব্যবহারের জন্য প্রথমে আপনার প্রজেক্টে নিম্নলিখিত প্যাকেজগুলি ইনস্টল করতে হবে:
Install-Package FluentNHibernate
এটি Fluent NHibernate-এর সমস্ত প্রয়োজনীয় ফাইল ইনস্টল করবে, যা আপনি পরবর্তীতে কোডের মধ্যে ব্যবহার করতে পারবেন।
2. Basic Configuration and Mapping
এখানে একটি সাধারণ উদাহরণ দেওয়া হলো যেটি দেখাবে কীভাবে Fluent NHibernate ব্যবহার করে কনফিগারেশন এবং ম্যাপিং করা যায়।
Model (Entity) Class
ধরা যাক, আমাদের একটি Product ক্লাস রয়েছে, যা একটি ডেটাবেস টেবিলকে প্রতিনিধিত্ব করছে।
public class Product
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual decimal Price { get; set; }
}
Fluent NHibernate Mapping
এখন Fluent NHibernate ব্যবহার করে এই Product ক্লাসের জন্য একটি ম্যাপিং তৈরি করি।
using FluentNHibernate.Mapping;
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Table("Products");
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Name).Not.Nullable();
Map(x => x.Price).Not.Nullable();
}
}
এখানে:
ClassMap<Product>: এটিProductক্লাসের জন্য Fluent NHibernate ম্যাপিং কনফিগারেশন তৈরি করে।Table("Products"): টেবিলের নাম সেট করা হয়েছে যা ডেটাবেসেProductsহবে।Id(x => x.Id): এটিIdপ্রপার্টি কনফিগার করে এবং জানায় যে, এটি একটি আইডেন্টিটি কলাম (অটোমেটিকালি ইনক্রিমেন্ট হবে)।Map(x => x.Name):Nameপ্রপার্টি ম্যাপিং করা হয়েছে, যা ডেটাবেসেNameকলাম হবে।
3. Configuration এবং SessionFactory Setup
Fluent NHibernate ব্যবহার করতে হলে আপনাকে NHibernate-এর SessionFactory কনফিগারেশনও Fluent API এর মাধ্যমে করতে হবে। এখানে কিভাবে SessionFactory কনফিগার করা যায় তা দেখানো হচ্ছে:
using NHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using System;
public class NHibernateHelper
{
private static ISessionFactory sessionFactory;
public static ISessionFactory SessionFactory
{
get
{
if (sessionFactory == null)
{
sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.Is("your_connection_string")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ProductMap>())
.BuildSessionFactory();
}
return sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
এখানে:
Fluently.Configure(): এটি Fluent NHibernate কনফিগারেশন শুরু করে।MsSqlConfiguration.MsSql2008.ConnectionString(): এটি আপনার ডেটাবেসের সংযোগ স্ট্রিং কনফিগার করে। আপনি এখানে SQL Server বা অন্যান্য ডাটাবেস কনফিগার করতে পারেন।Mappings(m => m.FluentMappings.AddFromAssemblyOf<ProductMap>()): এটি নির্দেশ করে যে,ProductMapক্লাসের ম্যাপিং যুক্ত করা হয়েছে এবং ডেটাবেস মডেল সংজ্ঞায়িত করা হয়েছে।BuildSessionFactory(): এটি একটিSessionFactoryতৈরি করে যা পরবর্তীতে ডেটাবেস অপারেশনের জন্য ব্যবহার করা হবে।
Fluent NHibernate এর অন্যান্য ফিচারসমূহ
- Inheritance Mapping: Fluent NHibernate ইনহেরিটেন্স ম্যাপিং সহজে কনফিগার করতে সাহায্য করে, যেমন
SubclassMap,JoinedSubclassMapইত্যাদি। - Custom Types: Fluent NHibernate কাস্টম টাইপ (যেমন, Enum, JSON, বা অন্য কাস্টম ডেটা টাইপ) ম্যাপিং করতে সাহায্য করে।
- Lazy Loading: এটি
lazy loadingএর জন্য খুবই উপযোগী, যাতে সেশন থেকে প্রয়োজনীয় ডেটা লোড করা হয়। - Cascading: এটি একাধিক অপারেশনের জন্য ক্যাসকেডিং কনফিগারেশন সাপোর্ট করে যেমন
Save,Delete,Updateইত্যাদি।
Fluent NHibernate এর মাধ্যমে Database Operations
Fluent NHibernate ব্যবহার করে, একবার SessionFactory কনফিগার করা হলে, আপনি ডেটাবেসের সাথে CRUD (Create, Read, Update, Delete) অপারেশন করতে পারবেন।
Save Operation Example
using (var session = NHibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var product = new Product { Name = "Laptop", Price = 1000 };
session.Save(product);
transaction.Commit();
}
}
এখানে:
session.Save(product): এটিproductঅবজেক্টটি ডেটাবেসে সেভ করে।transaction.Commit(): সেভ অপারেশনটি নিশ্চিত করার জন্য ট্রানজেকশন কমিট করা হচ্ছে।
সারাংশ
Fluent NHibernate একটি শক্তিশালী এবং কার্যকর উপায় যা NHibernate-এর জন্য কনফিগারেশন এবং ম্যাপিং আরও সহজ করে তোলে। এটি টাইপ-সেফ কোড লেখার সুবিধা দেয় এবং XML কনফিগারেশনের প্রয়োজনীয়তা হ্রাস করে। আপনি সহজেই ডেটাবেসের সাথে CRUD অপারেশন, ইনহেরিটেন্স, ক্যাশিং, কাস্টম টাইপস এবং আরও অনেক ফিচার ব্যবহার করতে পারেন।
NHibernate-এ Fluent Mapping Configuration এবং Convention Class ব্যবহারের মাধ্যমে আপনি ডেটাবেস টেবিলগুলোর সাথে ক্লাসের সম্পর্ক নির্ধারণ করতে পারেন। Fluent Mapping এনহাইবারনেট কনফিগারেশনের জন্য একটি শক্তিশালী এবং প্রোগ্রাম্যাটিক পদ্ধতি প্রদান করে, যা XML কনফিগারেশন ফাইলের পরিবর্তে কোড-ভিত্তিক কনফিগারেশন ব্যবহার করে। Convention Class ব্যবহার করে আপনি ডিফল্ট কনফিগারেশন পদ্ধতি সেট করতে পারেন, যা আপনার মডেল ক্লাসের জন্য সাধারণ রুলস নির্ধারণ করে।
Fluent Mapping Configuration
Fluent Mapping Configuration NHibernate এ মডেল ক্লাসের ম্যাপিং কনফিগার করার একটি প্রোগ্রাম্যাটিক পদ্ধতি। এটি আপনাকে ক্লাস, প্রোপার্টি এবং টেবিলের মধ্যে সম্পর্ক তৈরি করার জন্য আরও নমনীয়তা প্রদান করে। Fluent NHibernate একটি প্লাগইন হিসেবে কাজ করে, যা কনফিগারেশন এবং মডেল ম্যাপিংয়ের জন্য Fluent API প্রদান করে।
Fluent Mapping Example
ধরা যাক আমাদের একটি Employee ক্লাস আছে এবং এটি Employee টেবিলের সাথে ম্যাপ করতে হবে। নিচে এর উদাহরণ দেয়া হলো:
using FluentNHibernate.Mapping;
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual decimal Salary { get; set; }
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Table("Employee"); // টেবিল নাম নির্ধারণ
Id(x => x.Id).GeneratedBy.Identity(); // প্রাথমিক কী সেট করা
Map(x => x.Name).Length(100).Not.Nullable(); // Name প্রোপার্টি ম্যাপ করা
Map(x => x.Salary).Precision(18).Scale(2); // Salary প্রোপার্টি ম্যাপ করা
}
}
এখানে:
- Table() টেবিলের নাম নির্ধারণ করে।
- Id() মেথডের মাধ্যমে প্রাথমিক কী এবং তার জেনারেশন স্ট্রাটেজি নির্ধারণ করা হয়।
- Map() মেথড ব্যবহার করে অন্যান্য প্রোপার্টিগুলি টেবিলের কলামগুলির সাথে ম্যাপ করা হয়।
এটি Fluent NHibernate কনফিগারেশন ম্যাপিংয়ের একটি সাধারণ উদাহরণ।
Fluent NHibernate Configuration Setup
এখন, আপনাকে SessionFactory তৈরি করতে হবে যাতে Fluent Mapping ফাইলগুলো লোড করা যায়। এই কনফিগারেশনটি সাধারণত একটি FluentConfiguration অবজেক্টের মাধ্যমে সম্পন্ন করা হয়।
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
public class NHibernateHelper
{
public static ISessionFactory SessionFactory { get; private set; }
static NHibernateHelper()
{
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("your_connection_string"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<EmployeeMap>())
.BuildSessionFactory();
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
এখানে:
- Fluently.Configure() ব্যবহার করে NHibernate কনফিগার করা হচ্ছে।
- Mappings() মেথডের মাধ্যমে FluentMappings যোগ করা হচ্ছে, যা কনফিগারেশন ফাইলে ম্যাপিং তথ্য পাবে।
Convention Class তৈরি করা
NHibernate-এ Convention ক্লাস ব্যবহার করে আপনি সাধারণ কনফিগারেশন পদ্ধতি তৈরি করতে পারেন, যা আপনার সকল মডেল ক্লাসে প্রয়োগ হবে। Convention ক্লাস দ্বারা আপনি প্রাথমিক কী কিভাবে ম্যাপ হবে, প্রোপার্টির টাইপ এবং নাম কীভাবে ডেটাবেসের কলামগুলোর সাথে সম্পর্কিত হবে তা কাস্টমাইজ করতে পারেন।
উদাহরণ:
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.Instances;
public class CustomConvention : IClassConvention, IPropertyConvention
{
// টেবিল নাম কনভেনশন
public void Apply(IClassInstance instance)
{
instance.Table(instance.EntityType.Name); // টেবিল নাম হবে ক্লাস নামের মতো
}
// প্রোপার্টি নাম কনভেনশন
public void Apply(IPropertyInstance instance)
{
instance.Column(instance.Property.Name.ToLower()); // প্রোপার্টি নাম ডাটাবেস কলামে ছোট হাতেই থাকবে
}
}
এখানে:
- IClassConvention ইন্টারফেসটি ক্লাসের টেবিল নাম কাস্টমাইজ করতে সাহায্য করে।
- IPropertyConvention ইন্টারফেসটি প্রোপার্টির কলাম নাম কাস্টমাইজ করে।
এই CustomConvention ক্লাসটি সমস্ত ক্লাস এবং প্রোপার্টি ম্যাপিংয়ের জন্য সাধারণ কনভেনশন সেট করবে।
Fluent Configuration এর সাথে Convention Class ব্যবহার করা
Fluent Configuration-এ Convention Class যুক্ত করতে হলে, আপনাকে এটি Mappings() মেথডে অন্তর্ভুক্ত করতে হবে। নিচে তার উদাহরণ:
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
public class NHibernateHelper
{
public static ISessionFactory SessionFactory { get; private set; }
static NHibernateHelper()
{
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("your_connection_string"))
.Mappings(m =>
m.FluentMappings
.AddFromAssemblyOf<EmployeeMap>()
.Conventions.Add<CustomConvention>()) // Convention Class যোগ করা
.BuildSessionFactory();
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
এখানে:
- Conventions.Add() ব্যবহার করে কাস্টম কনভেনশন ক্লাসটি ফ্লুয়েন্ট কনফিগারেশনে অন্তর্ভুক্ত করা হয়েছে।
উপসংহার
Fluent Mapping Configuration এবং Convention Class ব্যবহার করে NHibernate-এর মডেল ম্যাপিং আরো বেশি নমনীয় এবং কাস্টমাইজযোগ্য করা যায়। Fluent NHibernate আপনাকে XML কনফিগারেশন ফাইলের পরিবর্তে কোড-বেসড কনফিগারেশন প্রদান করে, যা আরও দ্রুত এবং সোজা। Convention ক্লাসের মাধ্যমে আপনি সাধারণ কনফিগারেশন নিয়মাবলী (যেমন টেবিল ও কলাম নামের কনভেনশন) এক জায়গায় রেখে পুরো অ্যাপ্লিকেশন জুড়ে প্রয়োগ করতে পারেন।
NHibernate-এ Auto Mapping এবং Override Techniques খুবই শক্তিশালী কৌশল যা আপনাকে ORM (Object-Relational Mapping) মডেল তৈরি করতে সাহায্য করে। এই দুটি পদ্ধতি ব্যবহার করে, আপনি সহজেই ক্লাস এবং ডেটাবেস টেবিলের মধ্যে ম্যাপিং তৈরি করতে পারেন এবং প্রয়োজন অনুযায়ী কাস্টমাইজেশন করতে পারেন।
Auto Mapping
Auto Mapping একটি প্রক্রিয়া যা NHibernate কে ক্লাস এবং ডেটাবেস টেবিলের মধ্যে স্বয়ংক্রিয়ভাবে ম্যাপিং করতে নির্দেশ দেয়। এর মাধ্যমে, আপনি একটি ক্লাস তৈরি করে সেই ক্লাসের সমস্ত প্রপার্টি এবং সম্পর্ক ডেটাবেস টেবিলের সাথে স্বয়ংক্রিয়ভাবে ম্যাপ করতে পারেন। NHibernate Auto Mapping আপনাকে খুব কম কনফিগারেশন ও কোডে ম্যাপিং সম্পন্ন করতে দেয়, যা ডেভেলপারদের জন্য একটি বড় সুবিধা।
Auto Mapping ব্যবহার করার উদাহরণ
ধরা যাক, আমাদের একটি Employee ক্লাস রয়েছে এবং আমরা চাই এই ক্লাসটিকে ডেটাবেস টেবিলের সাথে স্বয়ংক্রিয়ভাবে ম্যাপ করতে।
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Position { get; set; }
public virtual DateTime HireDate { get; set; }
}
এখন, আপনি Auto Mapping কনফিগারেশন ব্যবহার করতে পারেন:
var configuration = new Configuration();
configuration.Configure(); // Hibernate.cfg.xml ফাইলের কনফিগারেশন লোড করবে
var mapper = new AutoMappingConfiguration();
var sessionFactory = configuration.BuildSessionFactory();
var session = sessionFactory.OpenSession();
এখানে, NHibernate স্বয়ংক্রিয়ভাবে Employee ক্লাসটি ডেটাবেস টেবিলের সাথে ম্যাপ করবে এবং আপনাকে ম্যানুয়ালি Mapping XML ফাইল বা Fluent API ব্যবহার করার দরকার হবে না।
Auto Mapping এর সুবিধা:
- সহজতা: Auto Mapping আপনাকে কম কনফিগারেশন এবং কোডে ম্যাপিং করতে দেয়।
- দ্রুত উন্নয়ন: আপনাকে Mapping ফাইল বা Fluent API দিয়ে সময় নষ্ট করতে হয় না।
- Maintenance: মডেল পরিবর্তন করলে NHibernate স্বয়ংক্রিয়ভাবে সবকিছু আপডেট করে, যা মেইনটেনেন্সের কাজ সহজ করে তোলে।
Override Techniques
যখন আপনি Auto Mapping ব্যবহার করেন, তখন NHibernate কিছু ক্ষেত্রে স্বয়ংক্রিয়ভাবে ক্লাসের প্রপার্টি এবং সম্পর্ক ম্যাপ করে দেয়। তবে, কিছু বিশেষ কেসে আপনাকে Override Techniques ব্যবহার করে কাস্টম ম্যাপিং করতে হতে পারে। এই কৌশলের মাধ্যমে, আপনি ক্লাসের প্রপার্টি বা টেবিলের সম্পর্ক কাস্টমাইজ করতে পারেন।
Override Techniques সাধারণত Property Override এবং Class Override এর মাধ্যমে করা হয়, যেখানে আপনি একাধিক প্রপার্টি বা ক্লাসের ম্যাপিং কাস্টমাইজ করতে পারেন।
1. Property Override
ধরা যাক, আমাদের Employee ক্লাসে একটি Salary প্রপার্টি রয়েছে, এবং আমরা চাই এই প্রপার্টিটিকে ডেটাবেসে একটি আলাদা নামের কলামে ম্যাপ করতে।
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Position { get; set; }
public virtual decimal Salary { get; set; }
}
এখন, আপনি Auto Mapping কনফিগারেশনের মধ্যে Salary প্রপার্টি কাস্টমাইজ করতে পারেন:
AutoMap.AssemblyOf<Employee>()
.Override<Employee>(map => map.Property(x => x.Salary).Column("AnnualSalary"));
এখানে, আমরা Salary প্রপার্টিকে ডেটাবেসের AnnualSalary নামক কলামের সাথে ম্যাপ করেছি।
2. Class Override
এখন, ধরুন আমরা চাই Employee ক্লাসের জন্য একটি কাস্টম টেবিল নাম নির্ধারণ করতে। এর জন্য আমরা ক্লাস লেভেলে Override ব্যবহার করতে পারি:
AutoMap.AssemblyOf<Employee>()
.Override<Employee>(map => map.Table("EmployeesTable"));
এখানে, Employee ক্লাসের জন্য ডেটাবেস টেবিলের নাম EmployeesTable নির্ধারণ করা হয়েছে।
Override Techniques এর সুবিধা:
- Customizability: আপনি যখন Auto Mapping ব্যবহার করেন, তখন কিছু কাস্টম ফিচার বা স্পেশাল ম্যাপিং করতে Override Techniques ব্যবহার করতে পারেন।
- Flexibility: যদি আপনার ডেটাবেসের কাঠামো বিশেষ ধরনের হয়, তবে আপনি Override Techniques দিয়ে অতিরিক্ত কাস্টমাইজেশন করতে পারবেন।
- Refinement: যখন সাধারণ Auto Mapping আপনার প্রয়োজনীয়তার সঙ্গে পুরোপুরি মিলে না, তখন Override Techniques এর মাধ্যমে আরো নির্দিষ্ট পরিবর্তন করা যায়।
Auto Mapping এবং Override Techniques একসাথে ব্যবহার
আপনি Auto Mapping এর সুবিধা নিতে পারেন এবং Override Techniques ব্যবহার করে প্রয়োজনীয় কাস্টমাইজেশন করতে পারেন। উদাহরণস্বরূপ:
var sessionFactory = new Configuration()
.Configure()
.AddAssembly("YourAssemblyName")
.BuildSessionFactory();
var mapper = AutoMap.AssemblyOf<Employee>()
.Override<Employee>(map => map.Property(x => x.Salary).Column("AnnualSalary"))
.BuildMapping();
এখানে, Auto Mapping স্বয়ংক্রিয়ভাবে সব প্রপার্টি এবং ক্লাস ম্যাপ করবে এবং আমরা Override ব্যবহার করে Salary প্রপার্টির জন্য কলাম নাম কাস্টমাইজ করেছি।
উপসংহার
Auto Mapping এবং Override Techniques দুটি অত্যন্ত গুরুত্বপূর্ণ কৌশল যা NHibernate ব্যবহারকারীদের জন্য অত্যন্ত সহায়ক। Auto Mapping আপনাকে দ্রুত ORM মডেল তৈরি করতে সাহায্য করে, এবং Override Techniques ব্যবহার করে আপনি ডেটাবেস টেবিল এবং ক্লাসের মধ্যে সম্পর্ক এবং প্রপার্টি কাস্টমাইজ করতে পারেন। একসাথে এই দুটি কৌশল ব্যবহার করলে আপনি একটি নমনীয়, ইফিশিয়েন্ট এবং মেইনটেনেবল ডেটাবেস অ্যাপ্লিকেশন তৈরি করতে পারবেন।
Fluent NHibernate হল NHibernate-এর জন্য একটি ফ্লুয়েন্ট API যা আপনাকে প্রোগ্রামেটিকভাবে মডেল ক্লাসগুলির জন্য ম্যাপিং কনফিগারেশন তৈরি করতে সহায়তা করে। এটি ডোমেইন মডেল এবং ডেটাবেস টেবিলের মধ্যে সম্পর্ক স্থাপন করতে সহজ এবং পরিষ্কার পদ্ধতি প্রদান করে। Complex Mapping কৌশলগুলি তখন ব্যবহার করা হয় যখন আপনার মডেল ক্লাসগুলো মধ্যে একাধিক সম্পর্ক, বিভিন্ন ধরনের কলাম মAPPING, বা কমপ্লেক্স ডেটা স্ট্রাকচার থাকতে পারে।
এখানে, Fluent NHibernate এর মাধ্যমে Complex Mapping সম্পর্কে কিছু উদাহরণ দেখানো হয়েছে যা আপনাকে একটি Complex Model বা Complex Class মডেল তৈরি এবং ম্যাপ করার জন্য সাহায্য করবে।
1. One-to-One Relationship Mapping
ধরা যাক, আপনার একটি Person ক্লাস এবং একটি Passport ক্লাস রয়েছে, যেখানে Person ক্লাসে একটি Passport অবজেক্ট রয়েছে এবং এটি One-to-One সম্পর্ক। এখানে, একজন ব্যক্তি একটিমাত্র পাসপোর্ট ধারণ করতে পারে এবং পাসপোর্ট শুধুমাত্র এক ব্যক্তির জন্য নির্ধারিত।
1.1 Entity Classes:
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Passport Passport { get; set; }
}
public class Passport
{
public virtual int Id { get; set; }
public virtual string PassportNumber { get; set; }
public virtual Person Owner { get; set; }
}
1.2 Fluent Mapping for One-to-One Relationship:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Table("Persons");
Id(x => x.Id);
Map(x => x.Name);
HasOne(x => x.Passport)
.Cascade.All() // If a Person is deleted, their Passport is also deleted
.Constrained(); // Foreign key will be created on the Passport table
}
}
public class PassportMap : ClassMap<Passport>
{
public PassportMap()
{
Table("Passports");
Id(x => x.Id);
Map(x => x.PassportNumber);
References(x => x.Owner)
.Cascade.None(); // Passport does not delete the person
}
}
এখানে, HasOne এবং References ব্যবহৃত হয়েছে One-to-One সম্পর্ক ম্যাপ করার জন্য।
2. One-to-Many Relationship Mapping
এটি একটি সাধারণ সম্পর্ক যেখানে একটি মডেল একাধিক সম্পর্কিত মডেল ধারণ করে। উদাহরণস্বরূপ, Order ক্লাস এবং OrderItem ক্লাস রয়েছে, যেখানে এক একটি অর্ডারের একাধিক আইটেম থাকতে পারে।
2.1 Entity Classes:
public class Order
{
public virtual int Id { get; set; }
public virtual string OrderNumber { get; set; }
public virtual IList<OrderItem> Items { get; set; } = new List<OrderItem>();
}
public class OrderItem
{
public virtual int Id { get; set; }
public virtual string ItemName { get; set; }
public virtual int Quantity { get; set; }
public virtual Order Order { get; set; }
}
2.2 Fluent Mapping for One-to-Many Relationship:
public class OrderMap : ClassMap<Order>
{
public OrderMap()
{
Table("Orders");
Id(x => x.Id);
Map(x => x.OrderNumber);
HasMany(x => x.Items)
.Cascade.All()
.Inverse(); // Inverse indicates the relationship is managed by OrderItem
}
}
public class OrderItemMap : ClassMap<OrderItem>
{
public OrderItemMap()
{
Table("OrderItems");
Id(x => x.Id);
Map(x => x.ItemName);
Map(x => x.Quantity);
References(x => x.Order)
.Column("OrderId"); // Foreign key column in OrderItems table
}
}
এখানে HasMany এবং References ব্যবহৃত হয়েছে। HasMany নির্দেশ করে যে একটি Order একাধিক OrderItem ধারণ করবে এবং Inverse ব্যবহার করা হয়েছে, যাতে OrderItem এর পক্ষ থেকে সম্পর্কের নিয়ন্ত্রণ করা যায়।
3. Many-to-Many Relationship Mapping
একটি Many-to-Many সম্পর্ক তখন ব্যবহৃত হয় যখন দুটি মডেল একে অপরের সাথে একাধিক সম্পর্ক থাকতে পারে। উদাহরণস্বরূপ, Student এবং Course ক্লাসে, যেখানে একজন ছাত্র একাধিক কোর্স নিতে পারে এবং একটি কোর্সে একাধিক ছাত্র থাকতে পারে।
3.1 Entity Classes:
public class Student
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Course> Courses { get; set; } = new List<Course>();
}
public class Course
{
public virtual int Id { get; set; }
public virtual string CourseName { get; set; }
public virtual IList<Student> Students { get; set; } = new List<Student>();
}
3.2 Fluent Mapping for Many-to-Many Relationship:
public class StudentMap : ClassMap<Student>
{
public StudentMap()
{
Table("Students");
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Courses)
.Cascade.All() // Both students and courses will be updated/deleted in sync
.Table("StudentCourses"); // Join table name
}
}
public class CourseMap : ClassMap<Course>
{
public CourseMap()
{
Table("Courses");
Id(x => x.Id);
Map(x => x.CourseName);
HasManyToMany(x => x.Students)
.Cascade.All()
.Table("StudentCourses");
}
}
এখানে, HasManyToMany পদ্ধতি ব্যবহার করা হয়েছে, যা Many-to-Many সম্পর্কের জন্য উপযুক্ত। এছাড়া, Join Table StudentCourses তৈরি করা হয়েছে যা এই সম্পর্কের জন্য মধ্যস্থ ভূমিকা পালন করবে।
4. Complex Type Mapping (Embedded Value Types)
কখনো কখনো আমাদের মডেল ক্লাসে একটি Complex Type থাকতে পারে, যেখানে একাধিক প্রপার্টি একটি একক কনসেপ্ট বা সত্তা হিসাবে ধারণ করা হয়। উদাহরণস্বরূপ, একটি Address ক্লাস হতে পারে যা একটি Person ক্লাসে এম্বেড করা।
4.1 Entity Classes:
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public virtual string Street { get; set; }
public virtual string City { get; set; }
public virtual string PostalCode { get; set; }
}
4.2 Fluent Mapping for Complex Type (Embedded Value Type):
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Table("Persons");
Id(x => x.Id);
Map(x => x.Name);
Component(x => x.Address, m =>
{
m.Map(x => x.Street);
m.Map(x => x.City);
m.Map(x => x.PostalCode);
});
}
}
public class AddressMap : ClassMap<Address>
{
public AddressMap()
{
Table("Addresses"); // This may not be required if Address is just an embedded value
Map(x => x.Street);
Map(x => x.City);
Map(x => x.PostalCode);
}
}
এখানে, Component ব্যবহার করা হয়েছে যা Complex Types এর জন্য ব্যবহৃত হয়। এতে, Address ক্লাসের ফিল্ডগুলো একটি একক সত্তার মতো মডেল করা হয়, কিন্তু বাস্তবে Person টেবিলেই ধারণ করা হয়।
সারাংশ
Fluent NHibernate এর মাধ্যমে Complex Mapping অত্যন্ত শক্তিশালী এবং নমনীয় পদ্ধতি। এটি আপনাকে সম্পর্কিত ডোমেন মডেলগুলির মধ্যে সম্পর্ক নির্ধারণ করতে এবং সঠিকভাবে ডেটাবেস টেবিলগুলিতে ম্যাপিং করতে সাহায্য করে। One-to-One, One-to-Many, Many-to-Many এবং Complex Type Mapping এর মাধ্যমে আপনি সহজেই শক্তিশালী এবং স্কেলেবল ডেটাবেস অ্যাপ্লিকেশন তৈরি করতে পারবেন।
Read more