1.0RC 版本中 Fluent Nhibernate Automapping 的问题
我是 NHibernate 的新手,在使 Automap 功能正常工作时遇到一些问题。这是我遇到的几个问题。
Fluent NHibernate 入门 wiki (http://wiki.fluentnhibernate.org/Getting_started) 定义了包含商店、产品和员工类别的示例以及这些类别的映射。我用 AutoMapping 替换了手动映射,并使用 Fluent NHibernate 生成架构。每件事都正确生成。但是,当应用程序尝试保存示例商店、产品和员工对象时,我收到错误“TransientObjectException 未处理:对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例。类型:FluentExample.Entities.Employee ,实体:FluentExample.Entities.Employee”。
自动映射如下所示:
.Mappings(m=>
m.AutoMappings.Add(
AutoMap.AssemblyOf<FluentExample.Entities.Employee>(type => type.Namespace == "FluentExample.Entities")))
对象创建代码(直接来自 wiki)如下所示。我应该提到的是,使用手动流畅映射时,对象创建工作正常。
// create a couple of Stores each with some Products and Employees
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" };
// add products to the stores, there's some crossover in the products in each
// store, because the store-product relationship is many-to-many
AddProductsToStore(barginBasin, potatoes, fish, milk, bread, cheese);
AddProductsToStore(superMart, bread, cheese, waffles);
// add employees to the stores, this relationship is a one-to-many, so one
// employee can only work at one store at a time
AddEmployeesToStore(barginBasin, daisy, jack, sue);
AddEmployeesToStore(superMart, bill, joan);
// save both stores, this saves everything else via cascading
session.SaveOrUpdate(barginBasin);
session.SaveOrUpdate(superMart);
transaction.Commit();
当尝试在我自己的一个类上使用 AutoMap 功能时,类是 创建,但由于某种原因,当我尝试实际创建时出现错误 插入一条记录。主要错误消息显示“AssertionFailure was 未处理:空值”。这是我的类的示例,config/ 映射、错误和创建表脚本。 (注:属性 类中的内容与 ASP.NET MVC 一起使用,与以下内容无关 NH.)
namespace Credit.Data.Entities
{
[Serializable]
public class EthnicityType
{
public EthnicityType()
{
}
[DisplayName("Id")]
[Required(ErrorMessage = "Id is required.")]
public virtual Guid Id { get; private set; }
[DisplayName("Title")]
[Required(ErrorMessage = "Title is required.")]
[StringLength(80, ErrorMessage = "Title must be less than 80 characters.")]
public virtual string Title { get; set; }
[DisplayName("Description")]
[StringLength(255, ErrorMessage = "Description must be less than 255 characters.")]
public virtual string Description { get; set; }
[DisplayName("Is Active")]
[Required(ErrorMessage = "Is Active is required.")]
public virtual bool IsActive { get; set; }
}
}
这是 Fluent NHibernate 配置。
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.FromConnectionStringWithKey ("CreditConnectionString"))
.UseReflectionOptimizer()
.AdoNetBatchSize(25)
.DefaultSchema("dbo")
.Cache(c => c
.UseQueryCache()
.ProviderClass<HashtableCacheProvider>())
.ShowSql())
.Mappings(m =>
m.AutoMappings.Add(AutoMap.AssemblyOf<Credit.Data.Entities.EthnicityType>(type => type.Namespace == "Credit.Data.Entities")))
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
还有错误。哎哟!
NHibernate.AssertionFailure was unhandled
Message="null identifier"
Source="NHibernate"
StackTrace:
at NHibernate.Engine.EntityKey..ctor(Object identifier, String
rootEntityName, String entityName, IType identifierType, Boolean
batchLoadable, ISessionFactoryImplementor factory, EntityMode
entityMode)
at NHibernate.Engine.EntityKey..ctor(Object id,
IEntityPersister persister, EntityMode entityMode)
at
NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate
(Object entity, EntityKey key, IEntityPersister persister, Boolean
useIdentityColumn, Object anything, IEventSource source, Boolean
requiresImmediateIdAccess)
at
NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object
entity, Object id, IEntityPersister persister, Boolean
useIdentityColumn, Object anything, IEventSource source, Boolean
requiresImmediateIdAccess)
at
NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId
(Object entity, String entityName, Object anything, IEventSource
source, Boolean requiresImmediateIdAccess)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId
(SaveOrUpdateEvent event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient
(SaveOrUpdateEvent event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate
(SaveOrUpdateEvent event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate
(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSaveOrUpdate
(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
at FluentExample.Program.PopulateRecordTest(ISessionFactory
sessionFactory) in C:\Code\FluentExample\FluentExample\Program.cs:line
52
at FluentExample.Program.BootstrapNH() in C:\Code\FluentExample
\FluentExample\Program.cs:line 32
at FluentExample.Program.Main() in C:\Code\FluentExample
\FluentExample\Program.cs:line 24
at System.AppDomain._nExecuteAssembly(Assembly assembly, String
[] args)
at
Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
还有表模式——只是为了好玩。
USE [Credit]
GO
/****** Object: Table [dbo].[EthnicityType] Script Date:
08/30/2009 04:59:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EthnicityType](
[ID] [uniqueidentifier] NOT NULL,
[Title] [nvarchar](80) NOT NULL,
[Description] [nvarchar](255) NULL,
[IsActive] [bit] NOT NULL
CONSTRAINT [PK_EthnicityType_Title] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY
= OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[EthnicityType] ADD CONSTRAINT
[DF_EthnicityType_ID] DEFAULT (newid()) FOR [ID]
GO
ALTER TABLE [dbo].[EthnicityType] ADD CONSTRAINT
[DF_EthnicityType_IsActive] DEFAULT ((1)) FOR [IsActive]
GO
我已经尝试了很多方法来让自动映射在我的环境中工作,但尚未完全成功。我尝试过的一些变化包括
- 使用静态地图并允许 Fluent Nhibernate 重新创建我的表。
- 将 Id 上的私有集更改为公共
- 创建主键约定来尝试设置 Guid,以防出现问题并将其添加到我的映射中。
主键约定:
public class PrimaryKeyConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.GeneratedBy.GuidComb();
//instance.GeneratedBy.Native();
}
}
非常感谢任何建议或反馈。
I am new to NHibernate and am running into some issues getting the Automap functionality to work properly. Here are a couple of issues I am having.
The getting started wiki for Fluent NHibernate (http://wiki.fluentnhibernate.org/Getting_started) defines a sample with store, product, and employee classes--as well as the mapping for those classes. I replaced the manual mapping with AutoMapping and used Fluent NHibernate to generate the schema. Every thing generated properly. However, when the application attempted to save sample store, product, and employee objects, I received an error "TransientObjectException was Unhandled: object references an unsaved transient instance - save the transient instance before flushing. Type: FluentExample.Entities.Employee, Entity: FluentExample.Entities.Employee".
The automap looks like:
.Mappings(m=>
m.AutoMappings.Add(
AutoMap.AssemblyOf<FluentExample.Entities.Employee>(type => type.Namespace == "FluentExample.Entities")))
The object creation code (straight from the wiki) looks like the following. I should mention that the object creation works fine when using the manual fluent mapping.
// create a couple of Stores each with some Products and Employees
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" };
// add products to the stores, there's some crossover in the products in each
// store, because the store-product relationship is many-to-many
AddProductsToStore(barginBasin, potatoes, fish, milk, bread, cheese);
AddProductsToStore(superMart, bread, cheese, waffles);
// add employees to the stores, this relationship is a one-to-many, so one
// employee can only work at one store at a time
AddEmployeesToStore(barginBasin, daisy, jack, sue);
AddEmployeesToStore(superMart, bill, joan);
// save both stores, this saves everything else via cascading
session.SaveOrUpdate(barginBasin);
session.SaveOrUpdate(superMart);
transaction.Commit();
When attempting to use the AutoMap functionality on one of my own classes, a class is
created, but for some reason I get errors when I attempt to actually
insert a record. The main error message says "AssertionFailure was
unhandled: null value". Here is a sample of my class, the config/
mapping, the error, and the create table script. (Note: The attributes
in the class are for use with ASP.NET MVC and have nothing to do with
NH.)
namespace Credit.Data.Entities
{
[Serializable]
public class EthnicityType
{
public EthnicityType()
{
}
[DisplayName("Id")]
[Required(ErrorMessage = "Id is required.")]
public virtual Guid Id { get; private set; }
[DisplayName("Title")]
[Required(ErrorMessage = "Title is required.")]
[StringLength(80, ErrorMessage = "Title must be less than 80 characters.")]
public virtual string Title { get; set; }
[DisplayName("Description")]
[StringLength(255, ErrorMessage = "Description must be less than 255 characters.")]
public virtual string Description { get; set; }
[DisplayName("Is Active")]
[Required(ErrorMessage = "Is Active is required.")]
public virtual bool IsActive { get; set; }
}
}
Here is the Fluent NHibernate configuration.
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.FromConnectionStringWithKey ("CreditConnectionString"))
.UseReflectionOptimizer()
.AdoNetBatchSize(25)
.DefaultSchema("dbo")
.Cache(c => c
.UseQueryCache()
.ProviderClass<HashtableCacheProvider>())
.ShowSql())
.Mappings(m =>
m.AutoMappings.Add(AutoMap.AssemblyOf<Credit.Data.Entities.EthnicityType>(type => type.Namespace == "Credit.Data.Entities")))
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
And the error. Yuk!
NHibernate.AssertionFailure was unhandled
Message="null identifier"
Source="NHibernate"
StackTrace:
at NHibernate.Engine.EntityKey..ctor(Object identifier, String
rootEntityName, String entityName, IType identifierType, Boolean
batchLoadable, ISessionFactoryImplementor factory, EntityMode
entityMode)
at NHibernate.Engine.EntityKey..ctor(Object id,
IEntityPersister persister, EntityMode entityMode)
at
NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate
(Object entity, EntityKey key, IEntityPersister persister, Boolean
useIdentityColumn, Object anything, IEventSource source, Boolean
requiresImmediateIdAccess)
at
NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object
entity, Object id, IEntityPersister persister, Boolean
useIdentityColumn, Object anything, IEventSource source, Boolean
requiresImmediateIdAccess)
at
NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId
(Object entity, String entityName, Object anything, IEventSource
source, Boolean requiresImmediateIdAccess)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId
(SaveOrUpdateEvent event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient
(SaveOrUpdateEvent event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate
(SaveOrUpdateEvent event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate
(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSaveOrUpdate
(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
at FluentExample.Program.PopulateRecordTest(ISessionFactory
sessionFactory) in C:\Code\FluentExample\FluentExample\Program.cs:line
52
at FluentExample.Program.BootstrapNH() in C:\Code\FluentExample
\FluentExample\Program.cs:line 32
at FluentExample.Program.Main() in C:\Code\FluentExample
\FluentExample\Program.cs:line 24
at System.AppDomain._nExecuteAssembly(Assembly assembly, String
[] args)
at
Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
And the table schema--just for kicks.
USE [Credit]
GO
/****** Object: Table [dbo].[EthnicityType] Script Date:
08/30/2009 04:59:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EthnicityType](
[ID] [uniqueidentifier] NOT NULL,
[Title] [nvarchar](80) NOT NULL,
[Description] [nvarchar](255) NULL,
[IsActive] [bit] NOT NULL
CONSTRAINT [PK_EthnicityType_Title] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY
= OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[EthnicityType] ADD CONSTRAINT
[DF_EthnicityType_ID] DEFAULT (newid()) FOR [ID]
GO
ALTER TABLE [dbo].[EthnicityType] ADD CONSTRAINT
[DF_EthnicityType_IsActive] DEFAULT ((1)) FOR [IsActive]
GO
I've tried a number of things to get automapping working in my environment but just have not yet been fully successful. Some variations I have tried include
- Using a static map and allowing Fluent Nhibernate to recreate my table.
- Changing the private set on Id to public
- Creating a primarykeyconvention to try and set the Guid in case that was the issue and adding this to my mapping.
Primary Key Convention:
public class PrimaryKeyConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.GeneratedBy.GuidComb();
//instance.GeneratedBy.Native();
}
}
Any advice or feedback is very much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Fluent NHibernate 示例实体位于
Examples.FirstProject.Entities
命名空间中,而您将 AutoMap 限制为FluentExample.Entities
(在type => type 中) .命名空间==“FluentExample.Entities”
)。第一条错误消息指出“引用未保存的瞬态实例 [...]FluentExample.Entities.Employee”,
您应该更新 AutoMap 代码以指向正确的接口。如果多个接口中有类,则可以修改条件以包含“或”。
The Fluent NHibernate example entities are in the
Examples.FirstProject.Entities
namespace, while you're limiting the AutoMap toFluentExample.Entities
(intype => type.Namespace == "FluentExample.Entities"
).The first error message points to that by stating "references an unsaved transient instance [...] FluentExample.Entities.Employee"
You should update the AutoMap code to point to the correct interface. If you have classes in multiple interfaces, you can modify the criteria to include an or.