8

ASP.NET Web サイトでサイト全体のグローバル設定を保持するものを作成しようとしています - サイト名、Google アナリティクスのアカウント番号、Facebook の URL など... サイトには複数の「ブランド」またはサブサイトを関連付けることができますそれを使用して、sitguid 列、それらをグループに入れるオプションも必要です。したがって、グループ列 – たとえば、TEST と PRODUCTION (web.config appsetting で設定)。

KEY をどこにもハードコーディングしたくありませんが、SiteSetting.getSetting(“SiteName”) などのコードでできるだけ簡単に参照できるようにしたいと考えています (これらはテンプレート (マスターページなど) で使用できます)。 )より多くのジュニア開発者が作成します)

また、管理コンソールで既存の設定を管理し、新しい設定を作成できるようにしたいと考えています。

datatype 列は編集フォーム用で、正しい入力要素を使用できます。たとえば、ビット タイプのチェックボックス、varchar のテキスト ボックスなどです。

現在の SiteSettings データベース テーブル:

  [sts_sitGuid] [uniqueidentifier] NOT NULL, -- tells us which site the setting is for
  [sts_group] [nvarchar](50) NOT NULL, -- used to group settings e.g. test/live
  [sts_name] [nvarchar](max) NULL, -- the display name of the setting, for edit forms
  [sts_alias] [nvarchar](50) NOT NULL, -- the name for the setting
  [sts_value] [nvarchar](max) NOT NULL, -- the settings value
  [sts_dataType] [nvarchar](50) NULL, -- indicates the control to render on edit form
  [sts_ord] [tinyint] NULL,  -- The order they will appear in on the admin form

私は現在、これを機能させる途中ですが、自分のやり方に満足していません。ここの人々が「正しい」解決策を見つけるのに役立つかもしれないアドバイスをお願いします! 私より前に人々がこれをやったと確信しています。(私がこれまでに持っているものを共有しますが、特定の方法で答えを歪めたくはありません) 私が探しているのは、これが最もよく行われる方法の概要であり、私のためにそれを書いてくれる人を探しているわけではありません。 )

私はこことGoogleの両方でかなりの検索を行いましたが、探しているもの、特に新しい設定の「定義」を追加したり、存在する設定を編集したりする機能を実際には見つけられませんでした.

システムは Web フォームを使用して ASP.NET で実行され、すべて c# で記述され、MSSQL 2008 を使用します。

いつものように、どんな助けも大歓迎です!

編集:明確にするために、これまでに構築したものを説明します。web.config やその他の xml ファイル、または別のデータベースを浮かび上がらせたくないので、これらすべてを SQL に格納することに固執しています。アプリケーションを他の顧客にロールアウトするときに、より多くのことを行うことができるからです。

これまでのところ、SiteSettings クラスがあり、これには GetSetting("SettingAlias") で呼び出して DB の "SettingAlias" の値を取得できるメソッド GetSetting があります。このクラスのコンストラクターは、現在のサイトのすべての設定をデータベースから取得し、それらをディクショナリに格納します。GetSetting はそのディクショナリから読み取ります。これまでのところ、その部分のすべてに満足しています。

私が苦労している部分は、編集フォームの生成です。これの以前のバージョンでは、設定を取得/設定するために Web サービスを使用していました。作業を保存するために同様のものを引き続き使用しようとしていますが、GoogleAnalyticsID、Sitename などのコードですべて定義されており、それぞれに列がありましたデータベースで、私が行っている変更は、代わりにこれらの設定を ROWS として保存することです (スキーマとすべての sitesettings クラスを変更する必要がないため、より簡単に追加できるため) 現在、私の SiteSettings クラスには、すべてを取得する SiteSettingsEditForm メソッドがあります。データベースからの情報、フォーム要素用の一連のコントロールを作成し、それを一時ページに配置して実行し、生成された HTML を ajax 経由で管理システムに渡します。これは間違っていると感じ、少しぎこちなく、ここに投稿する理由です。

要約すると、データベーステーブルから一握りの行をキャッシュして読み取ることができるクラスを作成し、編集フォームを提供する(またはフォームを生成するために他の何かにデータを提供する)クラスを作成したいと思います。同じデータベーステーブルの内容に基づく動的 (たとえば、タイプ列が「ビット」の場合はチェックボックスが必要で、「テキスト」の場合はテキスト入力が必要です)

4

5 に答える 5

4

この種の問題は、データ モデルから始めると視覚化しやすい場合があります。行ごとに設定が必要な場合は、2 つのテーブルがおそらくこれを格納する最良の方法です。

サイト:

SiteId SiteKey SiteName
1 XYGZ4345 クライアント サイト 1
2 AZT43752 クライアント サイト 2

これにより、設定したサイトのリストが定義されます。これを web.config に入れるように SiteKey を使用します。これをランダムな文字列または GUID に抽象化することをお勧めします (他の人の構成を誤ってロードするのを難しくするため)。クライアントは自分の名前を変更し、古い名前をキーなどとして使用しなかったため、将来混乱することはありません。

すべての設定を文字列として扱う場合、構成テーブル自体も単純です。

サイト設定:

SettingId SiteId SettingName SettingValue
1 1 ブランド KrustyBrand
2 1 GoogleID MSFTSUX0R
3 2 ブランド ConfigMasters(TM)

次に、すべての構成を非常に簡単にロードできます。

SELECT * FROM SiteSetting INNER JOIN Site ON (SiteSetting.SiteId = Site.SiteId) WHERE Site.SiteKey = 'XYGZ4345'

これで、次のようなクラスに格納できるキーと値のペアのリストができました。

public class SiteSetting
{
    public Site Site {
        get; set; //Site would just be a simple class consisiting of Id, Key and Name to match the database table
    }

    protected Dictionary<String, String> Settings { get; set; } //Simple key value pairs

}

したがって、これは非常に簡単な解決策です。ただし、さらに進めることができます - 考慮すべき事項:

1) これにどこかに環境を追加できますか?

環境ごとにサイトを追加することもできます

また

環境を SiteSetting テーブルに追加します。これの利点は、重複を避けるために enironment = 'ALL' を定義できることです。

また

構成がロードされるデータベースは、環境を定義します。そのため、アプリ構成で構成接続文字列を変更します。もちろん、別の環境に接続するには app.config を変更する必要がありますが、クライアント キーや環境を変更するために、いずれにせよそうしなければならない可能性があります。

2) ユーザー定義可能な設定の概念を追加します - 変更したい設定とロックしたい設定があります。「UserDefinable」を含むビット列を使用すると、これを整理できます

3) 設定の入力。

これは少し難しいです。次のようなものがあるかもしれません:

PropertyId PropertyName PropertyType フォーマット UserDefined
1 ブランド文字列 NULL 1
2 DatePresentation DateTime "yyyy-MM-dd" 1

次に、Settings テーブルは、値と PropertyId のみを定義します。これの利点は、保存している各設定に関する情報を増やし始め、設計がより正規化されるにつれてこの情報を再利用できることです。その後、Settings クラスは次のように変更されます。

public List<PropertyValue> { get; set; } //replacing the dictionary

PropertyValue は次のようになります。

public class PropertyValue
{
    int Id { get; set; }

    public string Name { get; set; }

    public string Value { get; set; }

    public string PVType { get; set; } //Could be an enum

    public string DisplayFormat { get; set;

    private string _RawValue;

    public string Value{
        get{
          switch(PVType){
            case "DateTime":
                    return Convert.ToDateTime(_RawValue).ToString(DisplayFormat);
            break;
            case "Double":
                    return Convert.ToDouble(_RawValue).ToString(DisplayFormat);
            break;
            default:
                    return _RawValue;
          }
        }
        set{
            _RawValue = value;
        }
    }

}

堅牢なエラー処理をサポートするには、Value メソッドなどを改善する必要があります (Convert.ChangeType を使用してスイッチ ブロックを簡素化することもできます)。

このトピックは、あなたが選択するのと同じくらい単純でも複雑でもあります ;-)

編集

それらの維持に関して; 非常に単純な GUI により、ユーザーはすべてのプロパティを表形式で表示できます。UserDefinable = 0 の行を読み取り専用として使用することを検討してください。それ以外の場合、ユーザーは行を編集および追加できます。たとえば、特に設定名が重複している場合は、検証する必要があります。

これを行う最も簡単な方法は、DataGrid を使用することです。シンプルなモックアップは次のようになります。

グリッド編集のモックアップ

そして、より洗練されたアプローチは次のようになります

したがって、フォームの生成は、PropertyValue オブジェクトのコレクションを選択したグリッド ソリューションにデータバインドするのと同じくらい簡単です。

于 2012-04-11T09:29:47.330 に答える
1

お気づきかもしれませんが、これを行うにはさまざまな方法があり、Microsoft が推奨するものから 100% 独自のものまであります。あなたは現在、スペクトルのロール・ユア・エンドにいますが、通常はどちらにしても良いと思います.

とにかく、基本的に探しているのは StateBag です。大まかに型付けされ、高度に構成可能であり、RDBMS にはあまり適していませんが、SQL Server が既に配置されている場合は、それを使用するのがおそらく最も簡単です。

オプション 1: Redis

ただし、別のオプションは、サイト構成用に Redis などを実行することです。キーと値のペアのコレクションとして Redis オブジェクトに保存し、JSON オブジェクトにプルしてから、それを Hashtable に変換すると、ルックアップが非常に高速になるか、その他のハッシュ可能なコレクションになります。コレクションを囲む単純なラッパー クラスで十分です。

Redis は非常に軽量で、多くの構成やメンテナンスは必要ありません。

オプション 2: SQL サーバー

あなたが言及した方法は実際にはかなり良い方法ですが、毎回データベースにクエリを実行するのではなく、厳密に型指定されたコレクションまたは Hashtable をキャッシュに入れて、数時間ごとに期限切れにします。

基本的に現在持っているものを使用する場合、次のように保存できます。

Setting
    SettingId Int PK,
    Key NVarchar(50),
    Name NVarchar(50),
    Description NVarchar(1000),
    Type NVarchar(50),
    Priority Int

Configuration
    SiteId Int,
    SettingId Int FK(Setting),
    SettingValue NVarchar(1000)

live/test/dev などをデータベースに保存しないでください。ライブ/テスト/開発/ステージ/QA などを区別するために、データベースとサーバーを完全に分離する必要があります。

于 2012-04-10T13:03:07.593 に答える
1

私は現在、すべての設定をプロパティとして持つクラスを作成することでこれを行っています

class Setting
{
GUID siteGuid{get; set;}
//other settings
}

SettingManager次に、このような静的クラスを作成しました

public static class SettingManager

{
private ConcurrentDictionary<GUID,Setting> settings= new ConcurrentDictionary<GUID,Setting>;
GetSetting(Guid siteGUID)
{
settings.TryGet(siteGuid);
Lastrefreshed = DateTime.Now;
//other code
}
Private DateTime LastRefreshedOn = DateTime.Now;
public void PopulateSetingsDic()
{
//populate the settings dictionary by getting the values from the database
}
}


コードのどこにでも名前空間を含めて設定を使用するだけです。変数を使用
して設定を1回または間隔ごとに入力できます。すべての設定がメモリ内にあるため、高速になります。 また、設定を動的に追加できるようにする必要がある場合は、データベースからの列名を使用して動的に設定を追加するか、単にマッピング を使用して、設定 ExpandoObject をここにキャストすることで設定を使用できます。文字列は、文字列に変換された GUID にすることができますapplication_startlastRefreshedOn

ExpandoObject
IDictionary<string,object>

編集:- http://zippedtech.blogspot.in/2012/04/dynaminism-in-net-40.htmlリンクを確認してください。このような問題の解決策について、新しい投稿を追加しました。

于 2012-04-10T13:13:32.353 に答える
0

私はxmlを使用し、xpathを「キー」として使用できるクラスを作成します
Ex. MySett.get("//level1/mysetting") or even MySett.get("//mysetting")

それぞれがコレクションを返すことができます。最初のものだけ、またはあなたが望むものは何でも。オーバーロードすることもできます。私が xml を気に入っているのは、それが優れた柔軟性を持っているからです。それ以外の場所でコードを削減するには、クラスを作成するだけです。欠点は、アプリケーションの起動時にドキュメントをロードし、シャットダウン時に保存する必要があることです。これは、vb コードのクラスの例です。(cコードは非常に似ていますが、当時はvbが稼働していたのでvbを使用しました

Imports System.Xml
Public Class XSett
Public xml As XmlDocument
Public Overloads Function gett(ByVal xp As String)
    Return CType(xml.SelectSingleNode(xp), XmlElement).InnerXml
    'by using inner xml, you can have either text setting 
    'or more markup that you might need for another function
    'your choice.  you could even cast it into another instance
    'of this class
End Function
Public Overloads Function gett(ByVal xp As String, ByVal sel As Integer)
    Return CType(xml.SelectNodes(xp)(sel), XmlElement).InnerXml
    'here, you can have multiple and choose the one you want
End Function
Public Overloads Sub gett(ByVal xp As String, ByRef col As Collection)
    Dim i As Integer
    Dim nds = xml.SelectNodes(xp)
    For i = 0 To nds.Count - 1
        col.Add(CType(nds(i), XmlElement).InnerXml)
    Next
    'Creted an entire collection of elemens.
    'i used vb's "collection" object, but any collection would do
End Sub
Public Overloads Sub sett(ByVal ap As String, ByVal name As String, ByVal data As String)
    'assume add here.
    'ap asks for existing parent element. eg: //guids
    'name ask for name of setting element
    Dim ts = xml.CreateElement(name)
    ts.InnerXml = data
    If ap = "" Then 'we assume document element
        xml.DocumentElement.AppendChild(ts)
    Else
        Dim p = CType(xml.SelectSingleNode(ap), XmlElement)
        p.AppendChild(ts)
    End If
End Sub
Public Overloads Sub sett(ByVal xp As String, ByVal sel As Integer, ByVal data As String)
    'just change existing setting
    CType(xml.SelectNodes(xp)(sel), XmlElement).InnerXml = data
End Sub
'naturally you can expand infinitely if needed
End Class
于 2012-04-10T16:57:44.843 に答える
-1

あなたの質問を正しく理解できれば、集中型の構成フレームワークを探していることになります。構成とサーバー管理については、通常はChefまたはPuppetをお勧めしますが、ASP.NET については簡単なグーグル検索を行ったところ、WCF ベースの構成サービスがうまくいくようです。私がリンクしたドキュメントは、 .NET StockTrader 5 サンプル アプリケーションで使用される構成サービスの段階的なチュートリアルです。

于 2012-04-10T11:58:45.077 に答える