Я новичок в NHibernate и сталкиваюсь с некоторыми проблемами при работе функции Automap для правильной работы. Вот несколько проблем, с которыми я столкнулся.
Вики для начала работы с Fluent NHibernate (http://wiki.fluentnhibernate.org/Getting_started) определяет образец с классами магазина, продукта и сотрудника, а также отображение для этих классов. Я заменил ручное отображение на AutoMapping и использовал Fluent NHibernate для генерации схемы. Каждая вещь генерируется правильно. Однако, когда приложение попыталось сохранить образцы хранилища, продукта и сотрудников, я получил ошибку "TransientObjectException is Unhandled: объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом. Тип: FluentExample.Entities.Employee, Entity: FluentExample.Entities.Employee ".
Автомат выглядит так:
.Mappings(m=>
m.AutoMappings.Add(
AutoMap.AssemblyOf<FluentExample.Entities.Employee>(type => type.Namespace == "FluentExample.Entities")))
Код создания объекта (прямо из вики) выглядит следующим образом. Я должен упомянуть, что создание объекта прекрасно работает при использовании ручного отображения данных.
// 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 был
unhandled: null value ". Вот пример моего класса, конфиг /
отображение, ошибка и сценарий создания таблицы. (Примечание: атрибуты
в классе для использования с 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
Я пробовал несколько вещей, чтобы заставить autopping работать в моей среде, но пока еще не был полностью успешным. Некоторые варианты, которые я пробовал, включают
- Использование статической карты и разрешение Fluent Nhibernate для воссоздания моей таблицы.
- Изменение частного набора на Id на public
- Создание основного ключа конвенции, чтобы попытаться установить Guid на случай, если это было проблемой, и добавление этого в мое отображение.
Соглашение о первичном ключе:
public class PrimaryKeyConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.GeneratedBy.GuidComb();
//instance.GeneratedBy.Native();
}
}
Любой совет или отзыв очень ценится.