提案された方法は、すべての場合に普遍性を主張するものではありませんが、その実装のための最小限のコストでロギングのシンプルかつ合理的に有益な方法です。
入門
技術的なタスクを持たないアプリケーションを開発していると想像してください。 要件と機能は常に変化しています。 そして、「何が何であるか」の定義は常に固定されているとは程遠い。 つまり すべてがいつでも変わる可能性があります。 このプロジェクトには、UI上のMSSQL + ASP.Net MVC3 +スクリプトの束が含まれます(スクリプトがない場合)。 データベースへのリンクは、Linqを通じて編成されます。 また、Webアプリケーションからデータベースへの接続が1人のユーザーからのものであることも重要な条件です。
そして、いつも書くことは非常に少ないです。
解決策は何ですか?
- 1.データベースレベルでのログ記録。 さまざまな方法があります。 それらの1つとして、これらは普遍的なトリガーです(インターネットには既製のメソッドに関する情報があります)。 しかし、ここには2つの問題があります。
- トリガーの追加を開始するとどうなりますか。
- 毎回ユーザー名を渡す必要があります。
一番下の行は、多くのコードと時間です。
- 2. Webアプリケーションレベルでのロギング。 この場合、必要なものはすべて揃っています。 両方のリクエスト、ユーザー、およびデータ。
- 3. IISログを使用できますが、他の多くのアプリケーションではログがケチです。 まあ、そして最も重要なこと-あなたはそれらの機能に制限があり、将来的にはあなたが必要に応じてロギングを変更することができなくなります。
ソリューションパス-Webアプリケーションレベルでのロギングパスを選択しました。
だから私たちは何が必要なのでしょう。
1. MSSQLでテーブルを作成する
2.ロギング用のクラスと最も単純なリポジトリを作成する
3. Global.asax.csにハンドラーを実装します
1. MSSQLでテーブルを作成する
ここではすべてが簡単です:
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/ BEGIN TRANSACTION SET QUOTED_IDENTIFIER ON SET ARITHABORT ON SET NUMERIC_ROUNDABORT OFF SET CONCAT_NULL_YIELDS_NULL ON SET ANSI_NULLS ON SET ANSI_PADDING ON SET ANSI_WARNINGS ON COMMIT BEGIN TRANSACTION GO CREATE TABLE dbo.Log ( LogID bigint NOT NULL IDENTITY (1, 1), UserName nchar(100) NOT NULL, IP nchar(20) NOT NULL, Controller nchar(200) NOT NULL, Action nchar(100) NOT NULL, Number int NOT NULL, Field nchar(100) NOT NULL, Value nchar(1000) NOT NULL, CreateDate datetime NOT NULL, GUID nchar(40) NOT NULL ) ON [PRIMARY] GO ALTER TABLE dbo.Log ADD CONSTRAINT DF_Log_CreateDate DEFAULT getdate() FOR CreateDate GO ALTER TABLE dbo.Log ADD CONSTRAINT PK_Log PRIMARY KEY CLUSTERED ( LogID ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO ALTER TABLE dbo.Log SET (LOCK_ESCALATION = TABLE) GO COMMIT
2.ロギングのクラス
テーブルマッピングクラス+リポジトリ自体が必要です。
テーブルを表示するためのクラス:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Linq.Mapping; namespace %Namespace%.Models.Log { [Table(Name="Log")] public class Log { [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)] public long LogID { get; set; } [Column()] public string UserName { get; set; } [Column()] public string IP { get; set; } [Column()] public string Controller { get; set; } [Column()] public string Action { get; set; } [Column()] public int Number { get; set; } [Column()] public string Field { get; set; } [Column()] public string Value { get; set; } [Column()] public string GUID { get; set; } } }
リポジトリクラス:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Linq; namespace %Namespace%.Models { public class LogRepository { protected Table< Log > table; public LogRepository (DataContext dataContext) { table = dataContext.GetTable< Log >(); } public void Add(Log entity) { table.InsertOnSubmit(entity); } public void SubmitChanges() { table.Context.SubmitChanges(); } } }
3. PreRequestHandlerExecuteイベントでGlobal.asax.csのハンドラーをハングさせます
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) { if (Request.RequestContext.RouteData.Values["controller"] == null) return; LogRepository logRepo = new LogRepository(new DataContext(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString)); string Controller = (Request.RequestContext.RouteData.Values["controller"]!=null?Request.RequestContext.RouteData.Values["controller"].ToString():"PanelSpecifications"); string Action = (Request.RequestContext.RouteData.Values["action"]!=null?Request.RequestContext.RouteData.Values["action"].ToString():"Index"); int counter = 0; string IP = Request.UserHostAddress; string UserName = User.Identity.Name; string GUID = Guid.NewGuid().ToString(); // start mark logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = "StartLog", Value = "StartLog", GUID = GUID } ); counter++; // full route data foreach (var item in Request.RequestContext.RouteData.Values) { if(item.Key.Trim().ToLower() != "controller" && item.Key.Trim().ToLower() != "action") { logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = item.Key??"", Value = Convert.ToString(item.Value)??"" , GUID = GUID } ); counter++; } } // Request Query String foreach (string key in Request.QueryString.Keys) { string Value = Convert.ToString(Request.QueryString[key]); logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = key??"", Value = Value??"" , GUID = GUID } ); counter++; } // Request Form Values foreach (string key in Request.Form.Keys) { string Value = Convert.ToString(Request.Form[key]); logRepo.Add(new Log() { Controller = Controller, Action = Action, IP = IP, UserName = UserName, Number = counter, Field = key??"", Value = Value??"" , GUID = GUID } ); counter++; } // save changes logRepo.SubmitChanges(); }
実際、すべて準備ができています。 これで、すべてのアクションが記録されます。
そして、あなたはいつもそのような身近な質問に答えることができます:
1.「誰のせいですか?」
2.「これをしたのは誰ですか?」
3.「これは間違いなくプログラムではありませんか? データの再編成は開始しませんでした!」
等
この方法は非常に簡単ですが、少なくともなんらかの方法でロギングホールを閉じます。 また、テーブルのどのフィールドとどのように記入されているかを注意深く見ると、これが質問の十分な部分をカバーしていることがわかります。