Fluent Nhibernate:将单个实体映射到接口需求
下午好 在我开始解释之前,我已经看了其他类似的问题,但细微的差异(主要是设计目的)意味着这些答案中提供的解决方案不适用于我 我正试图创建一个“基本数据访问库”,用于未来的项目,这样我就不必花时间在多个项目中编写相同的逻辑。其目的是简单地导入这个库,并立即拥有从IBaseDao继承的能力,并且从一开始就立即拥有标准的“CRUD”能力 因为(在编写这个基本库时)我无法确切地知道我的业务对象是什么(客户、文件结构、Cat、Dog、Order等),所以我在我的基本库中定义了一个接口,所有业务对象在与这个库一起使用之前都必须实现该接口。此类接口定义如下:Fluent Nhibernate:将单个实体映射到接口需求,nhibernate,fluent-nhibernate,interface,nhibernate-mapping,persistence,Nhibernate,Fluent Nhibernate,Interface,Nhibernate Mapping,Persistence,下午好 在我开始解释之前,我已经看了其他类似的问题,但细微的差异(主要是设计目的)意味着这些答案中提供的解决方案不适用于我 我正试图创建一个“基本数据访问库”,用于未来的项目,这样我就不必花时间在多个项目中编写相同的逻辑。其目的是简单地导入这个库,并立即拥有从IBaseDao继承的能力,并且从一开始就立即拥有标准的“CRUD”能力 因为(在编写这个基本库时)我无法确切地知道我的业务对象是什么(客户、文件结构、Cat、Dog、Order等),所以我在我的基本库中定义了一个接口,所有业务对象在与这个
public interface IEntity
{
/// Indicates weather this entity is used as test
/// data or if it is a real-world entity.
bool IsMockObject { get; set; }
/// This is not intended for use in a 'real' application
/// and is only used in testing.
string ReadableName { get; set; }
/// The unique identifier for this object.
Guid Id { get; set; }
}
因此,现在在“真实”应用程序中,我打算使用类似于以下内容的内容:
public class Customer : IEntity
{
public Customer()
{
}
string name = "";
public virtual String Name
{
get
{
return name;
}
set
{
name = value;
}
}
private DateTime birthday = DateTime.Now;
public virtual DateTime Birthday
{
get;
set;
}
private List<Order> orders = new List<Order>();
public virtual List<Order> Orders
{
get
{
return orders;
}
set
{
orders = value;
}
}
#region IEntity Members
private bool isMockObject;
public virtual bool IsMockObject
{
get
{
return true;
}
set
{
isMockObject = value;
}
}
private string readableName;
public virtual string ReadableName
{
get
{
return readableName;
}
set
{
readableName = value;
}
}
private Guid id;
public virtual Guid Id
{
get
{
return id;
}
set
{
id = value;
}
}
#endregion
}
公共类客户:IEntity
{
公众客户()
{
}
字符串名称=”;
公共虚拟字符串名
{
得到
{
返回名称;
}
设置
{
名称=值;
}
}
私人DateTime生日=DateTime.Now;
公共虚拟日期时间生日
{
得到;
设置
}
私有列表顺序=新列表();
公共虚拟列表命令
{
得到
{
退货订单;
}
设置
{
订单=价值;
}
}
#地区成员
私有布尔对象;
公共虚拟bool IsMockObject
{
得到
{
返回true;
}
设置
{
isMockObject=值;
}
}
私有字符串可读名;
公共虚拟字符串可读名
{
得到
{
返回readableName;
}
设置
{
readableName=值;
}
}
私有Guid id;
公共虚拟Guid Id
{
得到
{
返回id;
}
设置
{
id=值;
}
}
#端区
}
这就是问题所在。在我的单元测试期间,当我尝试保存一个“客户”时,我得到一个参数计数不匹配异常。我怀疑这个问题的原因是数据库中的Customer表不包含所有IEntity属性的列。但是,它确实包含一个Id列。到目前为止,我的CustomerMap如下所示:
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Table("Customer");
// From IEntity
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Birthday);
// From IEntity
Map(x => x.IsMockObject);
// From IEntity
Map(x => x.ReadableName);
HasMany(x => x.Orders);
}
}
公共类CustomerMap:ClassMap
{
公共客户映射()
{
表(“客户”);
//从理性
Id(x=>x.Id);
Map(x=>x.Name);
Map(x=>x.birth);
//从理性
映射(x=>x.IsMockObject);
//从理性
Map(x=>x.ReadableName);
有很多(x=>x个订单);
}
}
保存时,我实际希望NHibernate执行的操作是将Customer
特有的所有属性以及IEntity.Id
属性保存在Customer表中,然后将模拟对象的Id及其可读名称保存在名为(如果IsMockEntity为true)的单独表中
我发现类映射目前很难理解,因为我在NHibernate基础持久性方面做得很少。非常感谢您对相关资料的任何帮助或链接
谢谢您的时间。我要做的第一件事是
公共类客户
{
公众客户()
{
IsMockObject=true;
订单=新列表();
}
公共虚拟Guid Id{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟日期时间生日{get;set;}
//受保护:用户无法修改此项!
公共虚拟bool IsMockObject{get;protected set;}
公共虚拟字符串ReadableName{get;set;}
//需要是IList,而不是常规列表。
公共虚拟IList命令{get;set;}
}
_
我认为你的类地图没有任何问题,但我会先改变这些东西,然后看看有什么问题。如果仍然不起作用,请务必通知我们抛出的新异常。我要做的第一件事是
公共类客户
{
公众客户()
{
IsMockObject=true;
订单=新列表();
}
公共虚拟Guid Id{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟日期时间生日{get;set;}
//受保护:用户无法修改此项!
公共虚拟bool IsMockObject{get;protected set;}
公共虚拟字符串ReadableName{get;set;}
//需要是IList,而不是常规列表。
公共虚拟IList命令{get;set;}
}
_
我认为你的类地图没有任何问题,但我会先改变这些东西,然后看看有什么问题。如果仍然不起作用,请务必通知我们抛出的新异常。好的,我已经修改了代码以反映您建议的更改,并且还做了一些“挖掘”来尝试解决此问题。我现在拥有以下数据库结构: 标签
public class Customer
{
public Customer()
{
IsMockObject = true;
Orders = new List<Order>();
}
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual DateTime Birthday { get; set; }
// Protected: the user can't modify this!
public virtual bool IsMockObject { get; protected set; }
public virtual string ReadableName { get; set; }
// Needs to be an IList<T>, NOT a regular List<T>.
public virtual IList<Order> Orders { get; set; }
}
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Table("Customer");
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Birthday);
Join("MockEntities", me =>
{
Id<Guid>("Id");
me.Map(xx => xx.ReadableName);
me.Map(xx => xx.Id, "EntityId");
});
HasMany(x => x.Orders).Cascade.All().Not.LazyLoad();
}
}
public class OrderMap : ClassMap<Order>
{
public OrderMap()
{
Table("Order");
Id(x => x.Id);
Map(x => x.Price);
Map(x => x.CustomerId, "CustomerId");
Join("MockEntities", me =>
{
Id<Guid>("Id");
me.Map(xx => xx.ReadableName);
me.Map(xx => xx.Id, "EntityId");
});
}
}
at System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan()
at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior behavior, String method, ResultSetOptions options)
at System.Data.SqlServerCe.SqlCeCommand.ExecuteNonQuery()
at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Boolean[] notNull, Int32 j, SqlCommandInfo sql, Object obj, ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Object obj, ISessionImplementor session)
at NHibernate.Action.EntityInsertAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at MySolution.DataAccess.ConnectionProviders.NHibernateConnection.Create[TEntity](TEntity objectToCreate) in MySolution.DataAccess\ConnectionProviders\NHibernateConnection.cs:line 154
at MySolution.Testing.DataAccess.Connection.Testing_Connections.Function_NHibernateCreateNestedEntity()
NHibernate: INSERT INTO Customer (Name, Birthday, Id) VALUES (@p0, @p1, @p2);@p0 = 'David', @p1 = 03/09/2010 07:28:22, @p2 = 68fb7dd7-5379-430f-aa59-9de6007b2d56
NHibernate: INSERT INTO MockEntities (ReadableName, EntityId, Customer_id) VALUES (@p0, @p1, @p2);@p0 = 'Function_NHibernateCreateNestedEntity1', @p1 = 00000000-0000-0000-0000-000000000000, @p2 = 68fb7dd7-5379-430f-aa59-9de6007b2d56
07:28:28,851 ERROR [TestRunnerThread] AbstractBatcher [(null)]- Could not execute command: INSERT INTO MockEntities (ReadableName, EntityId, Customer_id) VALUES (@p0, @p1, @p2)
The column name is not valid. [ Node name (if any) = ,Column name = Customer_id ]
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Table("Customer");
Id(x => x.Id);
...
@p2 = 68fb7dd7-5379-430f-aa59-9de6007b2d56
@p2 = '68fb7dd7-5379-430f-aa59-9de6007b2d56'
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Table("Customer");
Id<Guid>(x => x.Id);
...
public interface IEntityBase
{
int Id { get; set; }
DateTime? Created { get; set; }
}
public abstract class EntityBase : IEntityBase
{
public int Id { get; set; }
public DateTime? Created { get; set ;}
}
public class Customer : EntityBase
{
public string Name { get; set; }
}
public class EntityBaseMap : ClassMap<EntityBase>
{
Id(x => x.Id);
Map(x => x.Created);
}
public class CustomerMap : SubclassMap<Customer>
{
Map(x => x.Name);
}