サービス機能を提供するコードをロードする Orchard CMS モジュールがあります。サービス コードは、ホストに依存しないように記述されており、以前は ASP.NET および WCF で使用されていました。サービス コードは MEF を使用してプラグインをロードします。そのようなプラグインの 1 つが監査用です。
監査のために Orchard データベースへのアクセスを許可するために、サービス コードを変更して、ホストが監査実装インスタンスを渡すこともできるようにしました。したがって、私の Orchard モジュールは、このインスタンスがオーチャード DB のレコードとして監査データを書き込むことを意図してサービスが開始されたときに、インスタンスを渡すことができます。
データベースの移行を作成しました。
public int UpdateFrom5()
{
SchemaBuilder.CreateTable("AuditRecord",
table => table
.Column<int>("Id", c => c.PrimaryKey().Identity())
.Column<int>("AuditPoint")
.Column<DateTime>("EventTime")
.Column("CampaignId", DbType.Guid)
.Column("CallId", DbType.Guid)
.Column<String>("Data")
);
return 6;
}
モデルで AuditRecord モデルを作成しました。
namespace MyModule.Models
{
public class AuditRecord
{
public virtual int Id { get; set; }
public virtual int AuditPoint { get; set; }
public virtual DateTime EventTime { get; set; }
public virtual Guid CampaignId { get; set; }
public virtual Guid CallId { get; set; }
public virtual String Data { get; set; }
}
}
モジュールの開始時に新しいインスタンスを挿入できるように、IDependency から派生する IAuditWriter インターフェイスを追加しました。
public interface IAuditWriter : IDependency
{
void WriteAuditRecord(AuditRecord data);
}
監査ライター インスタンスが既存のサービス コードと連携するには、サービス ライブラリで定義されている抽象クラス FlowSinkAudit から派生させる必要があります。抽象クラスは、Audit メソッドを定義します。サービスが監査を書き込む必要がある場合、サービスは、MEF を介して、または起動時にインスタンスを渡すことによってインスタンス化された FlowAuditSink 抽象クラスから派生したすべてのインスタンスで監査メソッドを呼び出します。
public class AuditWriter : FlowAuditSink, IAuditWriter
{
private readonly IComponentContext ctx;
private readonly IRepository<AuditRecord> repo;
public AuditWriter(IComponentContext ctx, IRepository<AuditRecord> repo)
{
this.ctx = ctx;
this.repo = repo;
}
public void WriteAuditRecord(AuditRecord data)
{
// Get an audit repo
//IRepository<AuditRecord> repo = (IRepository<AuditRecord>)ctx.Resolve(typeof(IRepository<AuditRecord>));
using (System.Transactions.TransactionScope t = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Suppress))
{
this.repo.Create(data);
}
}
public override void Audit(DateTime eventTime, AuditPoint auditPoint, Guid campaignId, Guid callId, IDictionary<String, Object> auditPointData)
{
// Add code here to write audit into the Orchard DB.
AuditRecord ar = new AuditRecord();
ar.AuditPoint = (int)auditPoint;
ar.EventTime = eventTime;
ar.CampaignId = campaignId;
ar.CallId = callId;
ar.Data = auditPointData.AsString();
WriteAuditRecord(ar);
}
}
私のサービス コードは、IOrchardShellEvents を実装するモジュール レベルのクラスから開始されます。
public class Module : IOrchardShellEvents
{
private readonly IAuditWriter audit;
private readonly IRepository<ServiceSettingsPartRecord> settingsRepository;
private readonly IScheduledTaskManager taskManager;
private static readonly Object syncObject = new object();
public ILogger logger { get; set; }
public Module(IScheduledTaskManager taskManager, IRepository<ServiceSettingsPartRecord> settingsRepository, IAuditWriter audit)
{
this.audit = audit;
this.settingsRepository = settingsRepository;
this.taskManager = taskManager;
logger = NullLogger.Instance;
}
...
"Activated" イベント中にサービスが開始さthis.Audit
れると、サービス インスタンスに渡します。
public void Activated()
{
lock (syncObject)
{
var settings = settingsRepository.Fetch(f => f.StorageProvider != null).FirstOrDefault();
InitialiseServer();
// Auto start the server
if (!StartServer(settings))
{
// Auto start failed, setup a scheduled task to retry
var tasks = taskManager.GetTasks(ServerAutostartTask.TaskType);
if (tasks == null || tasks.Count() == 0)
taskManager.CreateTask(ServerAutostartTask.TaskType, DateTime.Now + TimeSpan.FromSeconds(60), null);
}
}
}
...
private void InitialiseServer()
{
if (!Server.IsInitialized)
{
var systemFolder = @"C:\Scratch\Plugins";
if (!Directory.Exists(systemFolder))
Directory.CreateDirectory(systemFolder);
var cacheFolder = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/MyModule/Cache");
if (!Directory.Exists(cacheFolder))
Directory.CreateDirectory(cacheFolder);
Server.Initialise(systemFolder, cacheFolder, null, (FlowAuditSink)audit);
}
}
これらはすべて期待どおりに機能し、サービス コードは監査シンクを呼び出します。
私の問題は、監査シンクが呼び出され、監査をデータベースに書き込もうとしたときに、this.repo.Create(data)
何も書き込まれないことです。
また、IComponentContext インターフェイスを使用して新しいリポジトリ オブジェクトを作成しようとしましたが、このエラーはオブジェクトが既に破棄されています。これは、監査シンクが長寿命のオブジェクト インスタンスであるためだと思います。
結果に影響を与えない現在のトランザクションを中断して、または中断せずに両方を試みました。これは、呼び出しが ASP.NET MVC 経由ではなく、サービス コードによって作成されたスレッドから来ているためだと思います。
監査データをオーチャード データベースに表示する方法を誰か教えてもらえますか?
ありがとう
クリス。