FluentNHibernate,子集合依赖项
我尝试制作 FluentNHibernate 教程 的更有用的示例,但我对什么类型感到困惑从存储库请求时对象具有的依赖关系。基本上我希望对象是:
- 双向;所以我可以
- 从 NHibernate、存储库、会话中向上/向下遍历对象层次结构解耦(所有我还不太了解的东西)
- 无延迟加载(因为我不需要它,而且它对我有帮助(2),我认为)
我有点难以理解我所处理的示例是否、如何以及为什么实际上满足这些点。但是,当我请求一个列表并在代码中进行中断时,我看到子集合列表的类型是:
NHibernate.Collection.Generic.PersistentGenericBag<Store>
..这对我来说有点太复杂了..
所以,我的具体问题 是:
- 完全解耦需要哪些改变?,即检索简单列表的对象层次结构? (必须更改哪些主要概念、哪些类等)
我相信这就是我所需要的,因为;我为单个用户编写了一个单物理层应用程序,不需要“撤消逻辑”。我只是希望事情尽可能宽松,因为我觉得当我使用某种“推/拉”方法时,它会提供更可靠的代码。
产品类别:
public class Product
{
public int Id { get; private set; }
public string Name { get; set; }
public decimal Price { get; set; }
public IList<Store> StoresStockedIn { get; private set; }
public Product()
{
StoresStockedIn = new List<Store>();
}
}
商店类别:
public class Store
{
public int Id { get; private set; }
public string Name { get; set; }
public IList<Product> Products { get; set; }
public IList<Employee> Staff { get; set; }
public Store()
{
Products = new List<Product>();
Staff = new List<Employee>();
}
// AddProduct & AddEmployee is required. "NH needs you to set both sides before
// it will save correctly" ??
public void AddProduct(Product product)
{
product.StoresStockedIn.Add(this);
Products.Add(product);
}
public void AddEmployee(Employee employee)
{
employee.Store = this;
Staff.Add(employee);
}
}
员工类别:
public class Employee
{
public int Id { get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Store Store { get; set; }
}
映射:
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Name).Length(20);
Map(x => x.Price).CustomSqlType("decimal").Precision(9).Scale(2);
HasManyToMany(x => x.StoresStockedIn)
.Cascade.All()
.Inverse()
.Table("StoreProduct");
}
}
public class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Staff) // 1:m
.Inverse() // other end of relation is responsible for saving
.Cascade.All(); // Tells NH to cascade events
HasManyToMany(x => x.Products).Cascade.All()
.Table("StoreProduct"); // Set m:m join table
// ..only required for bi-directional m:m
}
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Id(x => x.Id); // By default an int Id is generated as identity
Map(x => x.FirstName);
Map(x => x.LastName);
References(x => x.Store).Cascade.None().Not.LazyLoad();
}
}
存储库:
public ICollection<Product> GetAll()
{
using (ISession session = FNH_Manager.OpenSession())
{
var products = session.CreateCriteria(typeof(Product)).List<Product>();
return products;
}
}
I attempt to make a more useful sample of the FluentNHibernate tutorial, but I'm confused about what type of dependencies the objects have when requested from the repository. Basically I want the objects to be:
- Bi-directional; so I can traverse up/down object hierarchy
- Decoupled from NHibernate, repository, sessions (all the things I don't understand too well yet)
- No-lazy load (Since I don't need it, and it helps me with (2), I think)
It's a bit hard for me to understand if, how and why the example I work on actually satisfy those points or not. But when I request a List and make a break in the code, I see that the child collection lists are of a type:
NHibernate.Collection.Generic.PersistentGenericBag<Store>
..which is a bit too complex for my head..
So, my concrete question is:
- What changes are required for complete decoupling?, i.e. to retrieve object hierarchies of simple Lists? (What main concepts, in what classes etc. that must be changed)
I believe this is what I need, since; I write a single-physical-tier application, for single user, with no requirement for "undo-logic". I just want things as loose as possible, as I feel it gives much more reliable code when I use kind of a "push/pull" approach.
Product class:
public class Product
{
public int Id { get; private set; }
public string Name { get; set; }
public decimal Price { get; set; }
public IList<Store> StoresStockedIn { get; private set; }
public Product()
{
StoresStockedIn = new List<Store>();
}
}
Store class:
public class Store
{
public int Id { get; private set; }
public string Name { get; set; }
public IList<Product> Products { get; set; }
public IList<Employee> Staff { get; set; }
public Store()
{
Products = new List<Product>();
Staff = new List<Employee>();
}
// AddProduct & AddEmployee is required. "NH needs you to set both sides before
// it will save correctly" ??
public void AddProduct(Product product)
{
product.StoresStockedIn.Add(this);
Products.Add(product);
}
public void AddEmployee(Employee employee)
{
employee.Store = this;
Staff.Add(employee);
}
}
Employee class:
public class Employee
{
public int Id { get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Store Store { get; set; }
}
Mapping:
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Name).Length(20);
Map(x => x.Price).CustomSqlType("decimal").Precision(9).Scale(2);
HasManyToMany(x => x.StoresStockedIn)
.Cascade.All()
.Inverse()
.Table("StoreProduct");
}
}
public class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Staff) // 1:m
.Inverse() // other end of relation is responsible for saving
.Cascade.All(); // Tells NH to cascade events
HasManyToMany(x => x.Products).Cascade.All()
.Table("StoreProduct"); // Set m:m join table
// ..only required for bi-directional m:m
}
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Id(x => x.Id); // By default an int Id is generated as identity
Map(x => x.FirstName);
Map(x => x.LastName);
References(x => x.Store).Cascade.None().Not.LazyLoad();
}
}
Repository:
public ICollection<Product> GetAll()
{
using (ISession session = FNH_Manager.OpenSession())
{
var products = session.CreateCriteria(typeof(Product)).List<Product>();
return products;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不太明白为什么你想进一步脱钩。
您公开的公共接口已经采用 IList 的形式。您可以将该 IList 公开为 IEnumerable。这将使它成为一个只读集合。 (您必须使用 FluentNHibernate 将其映射到字段而不是属性)
PersistentGenericBag 用于更改跟踪。
例如,NHibernate 如何知道何时添加实体或从列表中删除实体?
编辑:延迟加载的转变被认为是过早的优化。最好将其排除在映射之外,并在必要时在存储库中启用它。
I don't quite understand why you would want to decouple any further.
The public interface you are exposing is already in the form of an IList. You could expose that IList as an IEnumerable. That would make it a readonly collection. (you'd have to map it with FluentNHibernate to a field instead of a property)
The PersistentGenericBag is there for change tracking.
For example, how would NHibernate know when an entity was added, or removed from the list?
edit: Turning of lazy-loading is considered premature optimization. It's better to leave it out of the mappings and enable it in your repositories if you have to.