0

ソリューションに新しい WebApi プロジェクトを追加しました。コントローラーの Get メソッドは、 Xml を返す関数を呼び出します。Nhibernate ISession を使用してインスタンス化する関数を呼び出しています。Db に MySql を使用していますが、次のエラーが発生します。

ここにエラーのトレースがあります

<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Object reference not set to an instance of an object.
</ExceptionMessage>
<ExceptionType>System.NullReferenceException</ExceptionType>
<StackTrace>
at comp.rest.RestApi.Controllers.RestApiController.Get() in C:\GitHub\rea-rest\src\comp.rest.RestApi\Controllers\RestApiController.cs:line 23 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4() at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)
</StackTrace>
</Error>

アプリの起動時にglobal.asaxファイルから呼び出す依存関係リゾルバーがあります

public class ApiDependencyResolver : IDependencyResolver
    {
        private static ISession _session;
        private static ISettings _settings;
        private static IDiscountService _discountService;
        private static IAuctionService _auctionService;
        private static IAuditService _auditService;

        private NhProductAdminService productAdminService = new NhProductAdminService(_session, _settings,
                                                                                             _discountService,
                                                                                             _auctionService,
                                                                                             _auditService);

        public IDependencyScope BeginScope()
        {
            // This example does not support child scopes, so we simply return 'this'.
            return this;
        }

        public object GetService(Type serviceType)
        {
            if (serviceType == typeof(RestApiController))
            {
                return new RestApiController(productAdminService);
            }
            else
            {
                return null;
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return new List<object>();
        }

        public void Dispose()
        {
            // When BeginScope returns 'this', the Dispose method must be a no-op.
        }

    }

通常、コントローラーがヒットすると、Nhibernate セッションがインスタンス化されます。これは、global.asax Application_Start でセッションを既に開いているためです。これで数日間立ち往生しています。ばかげたことをしています。WebApi は初めてです。

この Web アプリケーションでは、global.asax を使用して Nhibernate セッションを開きます。

builder.RegisterModule(new WebNHibernateModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

WebHibernate クラスは次のようになります。

public class WebNHibernateModule : NHibernateModule
    {
        protected override IPersistenceConfigurer DatabaseConfig
        {
            get
            {
                return 
                    MySQLConfiguration.Standard
                        .ConnectionString(s => s.FromConnectionStringWithKey("ApplicationServices"))
                        .Driver<ProfiledSqlClientDriver>();
                //.ShowSql();
            }
        }

        protected override Action<MappingConfiguration> MappingConfig
        {
            get { return AutoConfig.Mappings; }
        }
    }

    public class ProfiledSqlClientDriver : MySqlDataDriver
    {
        public override IDbCommand CreateCommand()
        {
            var command = base.CreateCommand();

            if (MiniProfiler.Current != null)
            {
                command = DbCommandProxy.CreateProxy(command);
            }

            return command;
        }
    }

NHibernateModule クラスは次のようになります。

public abstract class NHibernateModule : Module
    {
        protected abstract IPersistenceConfigurer DatabaseConfig { get; }
        protected abstract Action<MappingConfiguration> MappingConfig { get; }

        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterGeneric(typeof(NhSessionQueryable<>)).As(typeof(IQueryable<>));
            builder.RegisterType<NhQueryContext>().As<IQueryContext>();

            builder.RegisterType<WebSessionTracker>().As<ISessionTracker>()
                .InstancePerHttpRequest();

            builder.Register(c => c.Resolve<ISessionFactory>().OpenSession())
                .InstancePerHttpRequest()
                .OnActivated(e =>
                {
                    e.Context.Resolve<ISessionTracker>().CurrentSession = e.Instance;
                    e.Instance.BeginTransaction();
                });

            builder.Register(c =>
                    Fluently.Configure().Database(DatabaseConfig)
                    .Mappings(MappingConfig)
                    .BuildConfiguration())
                .SingleInstance()
                .OnActivated(e =>
                {
                    e.Instance.Initialize(e.Context.Resolve<ValidatorEngine>());
                    new SchemaValidator(e.Instance).Validate(); // Validate the schema when we create the session factory
                });

            builder.Register(c => c.Resolve<Configuration>().BuildSessionFactory())
                .SingleInstance();
        }
    }

通常、Web アプリケーションでは、同様の Autofac を使用してセッションを事前設定します。WebApi についても同じことを行っていますが、Nhibernate セッションはまだ null です。

4

1 に答える 1

0

「セッション」という用語について混乱しているように聞こえます...

通常、MVC では、コントローラーがヒットするとセッションがインスタンス化されます。

NHibernate セッションは、ASP.NET (MVC) セッションと同じではありません。でNHibernateセッションを作成しISessionFactory.OpenSession()ます。NHibernate セッションを取得する方法の詳細については、ドキュメントの第 3 章を参照してください。

于 2013-10-11T20:24:03.663 に答える