2

db4o をデータストアとして使用して、ASP.NET MVC 2 で小さな Web アプリケーションを構築しています。

ここの例のように HttpModule を追加して、アプリケーションが db4o データベースにアクセスできるようにしました。VS2008 ASP.NET 開発サーバーの下の私の開発マシンでは、すべてが完全に機能しています。

ただし、アプリを Web ホストにデプロイしてアクセスしようとするとDatabaseFileLockedException、HttpModule がデータベース ファイルを開こうとする行でエラーが発生します。ただし、ファイルにアクセスするものは何もないはずです。実際、アプリの最初の実行では、この例外がスローされたときにのみ作成されます。

Web ホストのサーバーは Windows Server 2008 で IIS 7 を実行しており、アプリケーションは完全信頼で実行されています。それが違いを生む場合に備えて、それはサブアプリケーションです。

このエラーがライブサーバーで発生しているのに、開発サーバーではローカルに発生していない理由がわかりません。誰かが私を助けたり、次に何をすべきかを提案したりできますか?

4

3 に答える 3

3

それはサンプルコードの間違いです。HttpModule.Init は 1 回だけ呼び出されると想定していますが、これは必ずしも正しいとは限りません。アプリケーションの構成方法によっては、複数回呼び出すことができます。これを修正するには、インスタンスが既に存在する場合は HttpModule-Handler をチェックインします。

using System;
using System.Configuration;
using System.Web;
using Db4objects.Db4o;

namespace Db4oDoc.WebApp.Infrastructure
{
    public class Db4oProvider : IHttpModule
    {
        private const string DataBaseInstance = "db4o-database-instance";
        private const string SessionKey = "db4o-session";

        // #example: open database when the application starts
        public void Init(HttpApplication context)
        {
            if (null==HttpContext.Current.Application[DataBaseInstance])
            {
                HttpContext.Current.Application[DataBaseInstance] = OpenDatabase();
            }
            RegisterSessionCreation(context);
        }

        private IEmbeddedObjectContainer OpenDatabase()
        {
            string relativePath = ConfigurationSettings.AppSettings["DatabaseFileName"];
            string filePath = HttpContext.Current.Server.MapPath(relativePath);
            return Db4oEmbedded.OpenFile(filePath);
        }
        // #end example

        // #example: close the database when the application shuts down
        public void Dispose()
        {
            IDisposable toDispose = HttpContext.Current.Application[DataBaseInstance] as IDisposable;
            if (null != toDispose)
            {
                toDispose.Dispose();
            }
        }
        // #end example

        // #example: provide access to the database
        public static IObjectContainer Database
        {
            get { return (IObjectContainer)HttpContext.Current.Items[SessionKey]; }
        }
        // #end example

        // #example: A object container per request
        private void RegisterSessionCreation(HttpApplication httpApplication)
        {
            httpApplication.BeginRequest += OpenSession;
            httpApplication.EndRequest += CloseSession;
        }

        private void OpenSession(object sender, EventArgs e)
        {
            IEmbeddedObjectContainer container =
                (IEmbeddedObjectContainer)HttpContext.Current.Application[DataBaseInstance];
            IObjectContainer session = container.OpenSession();
            HttpContext.Current.Items[SessionKey] = session;
        }

        private void CloseSession(object sender, EventArgs e)
        {
            if (HttpContext.Current.Items[SessionKey] != null)
            {
                IObjectContainer session = (IObjectContainer)HttpContext.Current.Items[SessionKey];
                session.Dispose();
            }
        }
        // #end example
    }
}

代わりに、Global.apsx から Application_Start を使用することもできます。これは確実に 1 回だけ呼び出されます。

于 2010-08-09T08:48:01.367 に答える
2

ここで別の問題があります。

AppPools の再起動時に、古い AppPool が要求を終了し、新しい AppPool が新しい要求を処理しているときに重複が発生する可能性があります。

この間、2 つのプロセスが同じ db4o ファイルにアクセスしようとします。

これを回避するには、以下のハックのようなものを使用できます。

Db4oFactory.OpenServerの代わりに を使用していることに注意してくださいDb4oEmbedded.OpenFile。これにより、よりきめ細かいベースでのトランザクションの使用が可能になります。

public IObjectServer OpenServer()
{
    Logger.Debug("Waiting to open db4o server.");
    var attempts = 0;
    do
    {
        try
        {
            return Db4oFactory.OpenServer(fileName, 0);
        }
        catch (DatabaseFileLockedException ex)
        {
            attempts++;
            if (attempts > 10)
            {
                throw new Exception("Couldn't open db4o server. Giving up!", ex);
            }

            Logger.Warn("Couldn't open db4o server. Trying again in 5sec.");
            Thread.Sleep(5.Seconds());
        }
    } while (true);
}

お役に立てれば

于 2010-09-30T07:02:23.950 に答える
0

devで動作する場合、許可の問題のように聞こえます。同じディレクトリにメモ帳ファイルを貼り付けて、必要最小限のファイル コードでそれを開こうとします。同じ問題が発生するに違いありません。

于 2010-08-09T02:35:35.763 に答える