私の人生では、これを既存のコードで動作させることはできませんがenum
、NHibernate で選択内容を文字列として保存しようとしています。基本的に、UI チェック ボックスがあり、ユーザーが複数のチェック ボックスを選択した場合は、それらの選択を保存します。これで、NHibernate に 1 つの選択 (たとえば、ユーザーが 1 つの選択肢のみに制限されているドロップダウン リストまたはラジオ ボタン リストから) を保存することができます。
これは私が列挙型のために持っているものの要点です:
public enum IncomeType
{
[Display(Name = "Full-Time Employment")]
FullTime,
[Display(Name = "Part-Time Employment")]
PartTime,
[Display(Name = "Self-Employment")]
SelfEmployed,
[Display(Name = "Rental")]
Rental,
[Display(Name = "Social Security Payments")]
SocialSecurity,
[Display(Name = "Retirement / Pension Payments")]
Retirement,
[Display(Name = "Child Support Payments")]
ChildSupport,
[Display(Name = "Spousal Maintenance")]
Maintenance,
[Display(Name = "Other")]
Other
}
チェックボックス リストを表示するかどうかを「選択」するメソッドを使用します (myBulkItemThreshold
がオプションの数と等しい場合、チェックボックス リストが表示されます)。その方法は次のとおりです。
public static IEnumerable<SelectListItem> GetItemsFromEnumString<T>
(T selectedValue = default(T)) where T : struct
{
return from name in Enum.GetNames(typeof(T))
let enumValue = Convert.ToString((T)Enum.Parse(typeof(T), name, true))
select new SelectListItem
{
Text = GetEnumDescription(name, typeof(T)),
Value = enumValue,
Selected = enumValue.Equals(selectedValue)
};
}
(注: いくつかの項目にはヘルパーがありますが、それらが関連しているとは思いません。また、選択された入力はテンプレート.cshtml
ファイルを使用して表示されます - これも関連があるかどうかはわかりません)
今、私はこれを次のように呼びます:
public class IncomeTypeSelectorAttribute : SelectorAttribute
{
public override IEnumerable<SelectListItem> GetItems()
{
return Selector.GetItemsFromEnumString<IncomeType>();
}
}
そして最後に、virtual
(プロキシを使用して) プロパティに到達しますが、これは NHibernate がレンチをスローする場所です (注: これは NHibernate の前に私にとってはうまく機能していましたが、現在、多くのコード行を取得する必要なしにそれを操作しようとしています。すべてをやり直します; すべてをやり直すと、すでに動作させる必要があるコードがおそらく 3 倍になります):
プロパティ (レコード):
[IncomeTypeSelector(BulkSelectionThreshold = 9)]
public virtual List<string> IndividualIncomeTypeCheckBox { get; set; }
プロキシ (一部):
public List<string> IndividualIncomeTypeCheckBox
{
get { return Record.IndividualIncomeTypeCheckBox; }
set { Record.IndividualIncomeTypeCheckBox = value; }
}
繰り返しますが、これは私がやっていた方法であり、NHibernate の前はうまく機能していました。しかし今、NHibernate を使用する必要があります。それを回避する必要はありません。
Create メソッドで 2 つを結び付けて NHibernate を使用して DB に保存するサービス クラスを使用しています。上記の場合、通常は次のようになります。
part.IndividualIncomeTypeCheckBox = record.IndividualIncomeTypeCheckBox;
これは、選択が 1 つだけの場合に機能します。
さて、私はこれを機能させるために 2 か月を費やしました。ユーザーが 1 つしか選択できないコード (ラジオボタン リストなど) がたくさんあるので、大変です。例を挙げましょう:
public virtual IncomeType? IndividualIncomeTypeCheckBox { get; set; }
上記を実行すると、ドロップダウン リストが表示され、NHibernate はユーザーが選択した 1 つの許容可能なオプションを問題なく DB に保存します。ただし、複数のオプションはList<string>
機能しません。
今、私はここまたは他の場所で見つけることができるすべてを試しましたが、何も機能しません. IList<IncomeType>
はい、私はそれがまたは他の変種であるべきであることを知っています。しかし、これを使用する場合、NHibernate はそれIncomeType
が DB 内の別のテーブルである必要があります。これは、私が信じているような単純なことのために書くには多すぎるコードです。これは、複数の住所を持つユーザーではないという意味で、多対多の関係について話しているわけではありません (住所には、番地、都市、州、郵便番号などがあります)。
さまざまな種類のプロキシget
とset
コードを試しましたが、何も機能しません。私は試してみましたが[Flags]
、他のことstring
だけで動作しましたが、役に立ちませんでした。これらの最後のソリューションは「機能」しますが、複数の中から選択された最初の項目のみを保存します (つまり、私のシナリオでは、ユーザーが収入の種類として「フルタイム」と「レンタル」を選択した場合、「フルタイム」( string
) のみが保存されます)または "1" ( [Flags]
/ int
)、両方の項目が選択されていません。
ReadOnly
次のような属性を使用して選択肢を再表示する状況があります。
[IncomeTypeSelector]
[ReadOnly(true)]
public List<string> IndividualIncomeTypeCheckBoxPost
{
get { return IndividualIncomeTypeCheckBox; }
}
これはUIに表示されますが、NHibernateでこのようなことをしようとしましたが、うまくいきませんでした。
enum
上記を使用して、このチェックボックスリストのシナリオでNHibernateに複数を保存する方法を教えてください。
更新: こことウェブでさらに突っ込んで、次のことを思いつきました (まだ機能しません)。
プロパティ (レコード):
[IncomeTypeSelector(BulkSelectionThreshold = 9)]
public virtual IList<IncomeTypeRecord> IndividualIncomeTypeCheckBox
{
get { return incomeType; }
set { incomeType= value; }
}
private IList<IncomeTypeRecord> incomeType =
new List<IncomeTypeRecord>();
プロキシ (一部):
public IList<IncomeTypeRecord> IndividualIncomeTypeCheckBox
{
get { return Record.IndividualIncomeTypeCheckBox; }
set { Record.IndividualIncomeTypeCheckBox= value; }
}
そして列挙型への変更:
public enum IncomeType : int // removing int & value still gives validate error
{
[Display(Name = "Full-Time Employment")]
FullTime = 1,
[Display(Name = "Part-Time Employment")]
PartTime,
....
}
そして、サポートするためにこのクラスを追加しましたIncomeTypeRecord
public class IncomeTypeRecord
{
public virtual int Id { get; set; }
public virtual IncomeType Value { get; set; }
}
ただし、UI 画面に移動して 1 つ以上のオプションを選択すると、検証エラー (値が無効) が発生します。たとえば、FullTime だけを選択するか、FullTime と Retirement を選択すると、UI に次のエラーが表示されます。
値「FullTime」は無効です。
値 'FullTime,Retirement' は無効です。
(それぞれ)
int
の宣言を削除してenum
、「1」で開始した値を削除しても、この検証エラーが発生します。さまざまなモデルバインダーをいじって追加しようとしました(元の問題がまだ存在し、別の問題があるかどうかについて困惑していますが、それでも報奨金を獲得できます:))。
髪を引っ張ります。もっと報奨金を提供できれば、そうします。決定的な解決策が必要です。助けていただければ幸いです。
更新 これは私がこれまでに持っているものです:
記録:
public virtual string IndividualIncomeTypeCheckBox{ get; set; }
部:
//If I do IEnumberable<string> my .Select throws a cast error
public IEnumerable<IncomeType> IndividualIncomeTypeCheckBox
{
get
{
return Record
.IndividualIncomeTypeCheckBox
.Split(',')
.Select(r => (IncomeType)Enum.Parse(typeof(IncomeType), r));
}
set { Record.IndividualIncomeTypeCheckBox= value
== null ? null : String.Join(",", value); }
}
サービス クラス:
public SimplePart CreateSimple(SimplePartRecord record)
{
SimplePart simple = Services.ContentManager.Create<SimplePart>("Simple");
...
//How I would save a FirstName property (example Part / PartRecord below)
//public virtual string FirstName { get; set; } - PartRecord
//public string FirstName - Part
//{
// get { return Record.FirstName ; }
// set { Record.FirstName= value; }
//}
simple.FirstName = record.FristName;
...
//I obviously cannot do the following with the above IncomeType
//Getting cannot convert string to IEnumerable error
//How would I write this:
simple.IndividualIncomeTypeCheckBox = record.IndividualIncomeTypeCheckBox;
...
}
そして、これはコントローラーで呼び出される方法です(これはDBに永続化されます):(コントローラーコードの更新)
public ActionResult Confirm(string backButton, string nextButton)
{
if (backButton != null)
return RedirectToAction("WrapUp");
else if ((nextButton != null) && ModelState.IsValid)
{
_myService.CreateSimple(myData.SimplePartRecord);
return RedirectToAction("Submitted");
}
else
return View(myData);
}
追加コードによる更新 (シリアル化とビュー モデル):
「myData」はコントローラーで (シリアル化を使用して) 次のように定義されます。
private MyViewModel myData;
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var serialized = Request.Form["myData"];
if (serialized != null)
{
myData = (MyViewModel)new MvcSerializer().Deserialize
(serialized, SerializationMode.Signed);
TryUpdateModel(myData);
}
else
myData = (MyViewModel)TempData["myData"] ?? new MyViewModel();
TempData.Keep();
}
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (filterContext.Result is RedirectToRouteResult)
TempData["myData"] = myData;
}
フロントエンドでマルチステップ ウィザード (コントローラー アクション "backButton" "nextButton" に見られるように) をセットアップするため、シリアライゼーションを使用します。 ~/Views フォルダーの直下にある .cshtml ファイルのみ (私が使用しているような構造化されたフォルダー リストではありません)) ドライバーなし = 更新ビュー モデル タイプ コードなし = DB にデータを「作成」するメカニズムなし。 「作成」タイプのメソッドは使用しません。フォームは送信されますが、すべてのデータは「NULL」になります。
データを自動的に永続化する必要があるとのことですが、申し訳ありませんが、方法がわかりません。私が読んだものやレビューしたコードには、フォームに入力されたものでDBを更新するいくつかの方法があります。何か不足している場合は、お詫び申し上げます。
「MyViewModel」は非常に簡単です。
[Serializabel]
public class MyViewModel
{
public SimplePartRecord SimplePartRecord { get; set; }
}
念のため、移行の関連部分を次に示します (戻り値 1 は、完全に別の無関係なテーブルです)。
public int UpdateFrom1()
{
SchemaBuilder.CreateTable("SimplePartRecord",
table => table
.ContentPartRecord()
...
.Column("IndividualIncomeTypeCheckBox", DbType.String)
...
);
ContentDefinitionManager.AlterPartDefinition("SimplePart",
part => part
.Attachable(false));
return 2;
}
私が得ているエラーは
タイプ 'string' を 'System.Collections.Generic.IEnumerable' に暗黙的に変換することはできません"
サービスクラスの「Create」メソッドで次のことを行うと:
simple.IndividualIncomeTypeCheckBox = record.IndividualIncomeTypeCheckBox;
追加の考え: nn Relation サンプルを使用して、このシナリオを処理しようとしました。単純明快にすべきだと思っていたコードが余分にたくさんあることは別として、シリアライゼーションの使用方法が原因で、多くのオブジェクト参照エラーが発生し、それを処理するためにコントローラーを適切にコーディングする方法を理解できませんでした。