Fluent NHibernate-升级TPC层次结构中的类
本文关键字:层次结构 TPC NHibernate- 升级 Fluent | 更新日期: 2023-09-27 17:59:50
在给定的情况下,我有多个从基类继承的类,在Table Per Concrete Class
层次结构中,我遇到可能需要将类从较低级别"升级"到更高级别的情况。
例如,我将使用类Employee
-> Manager
演示。
class Employee {
Guid Id { get; set; }
// certain properties
}
class Manager : Employee {
// certain unique properties
}
EmployeeMap : ClassMap<Employee> {
// mapping information
}
ManagerMap : SubClassmap<Manager> {
// appropriate unique properties mapping
}
var employee = new Employee {
Name = "Some Employee"
}
session.Save(employee);
现在,过了一会儿,那个Employee
被撞到Manager
,那么现在我该怎么办? dbo.Employees
和dbo.Managers
是不同的表。如何从较低等级升级到较高等级而不丢失现有等级的所有内容?
不幸的是,我想不出任何方法来整齐地执行此更新 - 因为您使用的是每个具体类的表,所以我能想到的唯一方法是删除现有员工并添加新经理。
话虽如此,我确实有一些可能对你有帮助的东西 - 我出于不同的原因需要它,但它也可能对你的情况有所帮助。
下面的类使用反射来提供通用的"复制"机制。要使用它,请尝试以下代码片段(假设员工是获得晋升的员工(:
var manager = new Manager;
var copier = new PropertyCopier<Employee,Manager>(employee, manager);
copier.Copy();
经理对象现在应具有与雇员对象相同的属性值(至少在两个类中都存在该属性时(。现在,您可以提交经理并删除原始员工。
PropertyCopier 类代码如下:
using System;
using System.Reflection;
// ... You will want this in your own namespace not mine. ;-)
///<summary>
/// Copies properties with the same name and type from one object to another.
///</summary>
///<typeparam name="TFirst">The object type to copy from.</typeparam>
///<typeparam name="TSecond">The object type to copy to.</typeparam>
public class PropertyCopier<TFirst, TSecond>
where TFirst : class
where TSecond : class
{
private readonly TFirst _first;
private readonly TSecond _second;
///<summary>
/// Creates an instance of the PropertyCopier.
///</summary>
///<param name="first">The object to copy properties from.</param>
///<param name="second">The object to copy properties to.</param>
///<exception cref="ArgumentNullException">An <see cref="ArgumentNullException"/> will be thrown if
/// the source or destination objects are null.</exception>
public PropertyCopier(TFirst first, TSecond second)
{
if ( first == null )
{
throw new ArgumentNullException("first");
}
if (second == null)
{
throw new ArgumentNullException("second");
}
_first = first;
_second = second;
}
///<summary>
/// Performs the copy operation.
///</summary>
public void Copy()
{
Copy(p => true);
}
///<summary>
/// Performs the copy operation, omitting any items for which the predicate evaluates to false.
///</summary>
///<param name="predicate">A predicate based on the <see cref="PropertyInfo"/> used to determine if the property should be copied.</param>
///<exception cref="ArgumentException">An <see cref="ArgumentException"/> may be thrown if the copy cannot be performed.
/// This may happen if, for example, there is a property with the same name but a different type.</exception>
public void Copy(Predicate<PropertyInfo> predicate)
{
foreach (PropertyInfo info in typeof(TFirst).GetProperties())
{
PropertyInfo infoInDestination = null;
try
{
infoInDestination = typeof(TSecond).GetProperty(info.Name, info.PropertyType);
}
catch (AmbiguousMatchException)
{
}
try
{
if (infoInDestination != null && infoInDestination.CanWrite && predicate(infoInDestination))
{
infoInDestination.SetValue(_second, info.GetValue(_first, null), null);
}
}
catch (Exception e)
{
throw new ArgumentException(String.Format("Unable to copy property called {0}", info.Name), e);
}
}
}
}
希望这有帮助!