Asp.net mvc 3 尝试根据Orchard中的枚举保存复选框选择(NHibernate)
我花了五(5)天的大部分时间试图找出如何使这项工作: 我使用Asp.net mvc 3 尝试根据Orchard中的枚举保存复选框选择(NHibernate),asp.net-mvc-3,nhibernate,orchardcms,Asp.net Mvc 3,Nhibernate,Orchardcms,我花了五(5)天的大部分时间试图找出如何使这项工作: 我使用enum,通过单选按钮列表、下拉列表(这些是多个选项中的一(1)个选项)以及复选框列表和多选列表(这些是多个选项中的一(1)对所有选项)存储用户输入的“选项” 现在,使用单选按钮列表和下拉列表,我在Orchard数据库中保存时没有问题。用户选择一个选项,该选项将作为所选的特定enum保存到数据库中 但是,使用复选框列表或多选择列表,我无法让Orchard/NHibernate保存多个选定的枚举 我已经尝试了所有我能在SO上或通过Goog
enum
,通过单选按钮列表、下拉列表(这些是多个选项中的一(1)个选项)以及复选框列表和多选列表(这些是多个选项中的一(1)对所有选项)存储用户输入的“选项”
现在,使用单选按钮列表和下拉列表,我在Orchard数据库中保存时没有问题。用户选择一个选项,该选项将作为所选的特定enum
保存到数据库中
但是,使用复选框列表或多选择列表,我无法让Orchard/NHibernate保存多个选定的枚举
我已经尝试了所有我能在SO上或通过Google搜索找到的东西。唯一“可行”的解决方案是创建一个新表(通过迁移)/部分/部分记录组合,在某些情况下仅存储7-8个选项,这在这种情况下是过分的。然后,当然,我可以做一些类似于公共虚拟IList{get;set;}
的事情
是的,我看过果园里的文件。有人认为,LazyField
可能是一个解决方案。但看来(至少在我找到的信息或我看过的代码示例中,LazyField
处理的是一个单独的表场景
请告诉我,我不需要一张单独的桌子来完成我想要完成的事情。再一次,这似乎是矫枉过正
下面是一个简单的例子,说明我正在尝试做什么:
public enum MyEnum
{
Enum1,
Enum2,
Enum3,
Enum4,
Enum5
}
Selector.cs
有助于自动选择单选按钮、下拉列表、复选框或多选列表:
public class MySelectorAttribute : SelectorAttribute
{
public override IEnumerable<SelectListItem> GetItems()
{
return Selector.GetItemsFromEnum<MyEnum>();
}
}
Part.cs
:
[MyEnumSelector]
public virtual IList<string> MyEnumCheckBox { get; set; }
public IList<string> MyEnumCheckBox
{
get { return Record.MyEnumCheckBox; }
set { Record.MyEnumCheckBox = value; }
}
public IList MyEnumCheckBox
{
获取{return Record.MyEnumCheckBox;}
设置{Record.MyEnumCheckBox=value;}
}
注意:当我使用
时,我得到一个“表不存在”错误。如果改用
,则会出现强制转换错误(generic.list v.generic.icollection或某些变体)
我尝试了IEnumerable
和ICollection
这两种方法,但都有不同的错误消息
我不得不想象,Orchard/NHibernate会允许这种行为,而不需要我创建一个新的表来引用(在这种情况下,这似乎又是过分了)
如果有人能帮忙,我将不胜感激。我对这个问题束手无策。赏金?现金?你说吧。是的,我很绝望 您根本无法映射这样的列表。您需要与另一个记录/表建立适当的关系,或者可以使用逗号分隔的值列表等来管理存储。第一种情况当然有点干净,但是如果您不期望给定记录有太多的值,那么第二种情况就更容易了,而且坦率地说也很好
你可能还想考虑一个EnUM字段。
< p>你可以用<代码> [旗子] < /Cord>属性装饰你的<代码> Enm MyEnUng/<代码>,并将它的项的值设置为2的不同幂。例如,您的枚举可能如下所示:
[Flags]
public enum MyEnum
{
Enum1 = 1,
Enum2 = 2,
Enum3 = 4,
Enum4 = 8,
Enum5 = 16
}
现在,PartRecord
类的MyEnumCheckBox
属性将是int
类型:
public virtual int MyEnumCheckBox { get; set; }
您可以在部分
类中创建代理属性。例如:
private IList<MyEnum> _myCheckBox;
[MyEnumSelector]
public IList<MyEnum> MyCheckBox
{
get
{
if (_myCheckBox == null)
{
_myCheckBox = new List<MyEnum>();
foreach (MyEnum item in Enum.GetValues(typeof(MyEnum)))
{
if (((MyEnum)Record.MyEnumCheckBox & item) == item)
_myCheckBox.Add(item);
}
}
return _myCheckBox;
}
set
{
_myCheckBox = value;
Record.MyEnumCheckBox = 0;
foreach (var item in value)
{
Record.MyEnumCheckBox |= (int)item;
}
}
}
private IList\u myCheckBox;
[髓鞘选择器]
公共IList MyCheckBox
{
得到
{
如果(_myCheckBox==null)
{
_myCheckBox=新列表();
foreach(Enum.GetValues中的MyEnum项(typeof(MyEnum)))
{
if(((MyEnum)Record.MyEnumCheckBox&item)=item)
_myCheckBox.Add(项目);
}
}
返回我的复选框;
}
设置
{
_myCheckBox=值;
Record.MyEnumCheckBox=0;
foreach(价值中的var项目)
{
Record.MyEnumCheckBox |=(int)项;
}
}
}
您可以找到有关Flags属性的更多信息。它基本上是为了使您能够对一个枚举字段使用多个枚举值,而这正是您要查找的内容
编辑:
我花了点时间构建了一个自定义模块来演示这项技术。我已经测试过了,它的工作方式应该是这样的。以下是消息来源:
迁移.cs
public int Create()
{
SchemaBuilder.CreateTable("MultipleEnumPickerRecord", table => table
.ContentPartRecord()
.Column<int>("SelectedItems"));
ContentDefinitionManager.AlterPartDefinition("MultipleEnumPickerPart", p => p.Attachable());
return 1;
}
public int Create()
{
CreateTable(“MultipleEnumPickerRecord”,table=>table
.ContentPartRecord()
。栏(“SelectedItems”);
ContentDefinitionManager.AlterPartDefinition(“MultipleEnumPickerPart”,p=>p.Attachable());
返回1;
}
型号:
[Flags]
public enum MyEnum
{
Enum1 = 1, // bit-wise 00001 or 2^0
Enum2 = 2, // bit-wise 00010 or 2^1
Enum3 = 4, // bit-wise 00100 or 2^2
Enum4 = 8, // bit-wise 01000 or 2^3
Enum5 = 16 // bit-wise 10000 or 2^4
}
public class MultipleEnumPickerRecord : ContentPartRecord
{
public virtual int SelectedItems { get; set; }
}
public class MultipleEnumPickerPart : ContentPart<MultipleEnumPickerRecord>
{
private IList<MyEnum> _selectedItems;
public IList<MyEnum> SelectedItems
{
get
{
if (_selectedItems == null)
{
_selectedItems = new List<MyEnum>();
foreach (MyEnum item in Enum.GetValues(typeof(MyEnum)))
{
if (((MyEnum)Record.SelectedItems & item) == item)
_selectedItems.Add(item);
}
}
return _selectedItems;
}
set
{
_selectedItems = value;
Record.SelectedItems = 0;
foreach (var item in value)
{
Record.SelectedItems |= (int)item;
}
}
}
}
[标志]
公共枚举髓鞘
{
Enum1=1,//按位00001或2^0
Enum2=2,//按位00010或2^1
Enum3=4,//按位00100或2^2
Enum4=8,//按位01000或2^3
Enum5=16//按位10000或2^4
}
公共类MultipleNumpicKerreCord:ContentPartRecord
{
公共虚拟int SelectedItems{get;set;}
}
公共类MultipleEnumPickerPart:ContentPart
{
私人IList _selectedItems;
公共IList SelectedItems
{
得到
{
如果(_selectedItems==null)
{
_selectedItems=新列表();
foreach(Enum.GetValues中的MyEnum项(typeof(MyEnum)))
{
if(((MyEnum)Record.SelectedItems&item)=item)
_选择编辑项。添加(项);
}
}
返回_selectedItems;
}
设置
{
_selectedItems=值;
Record.SelectedItems=0;
foreach(价值中的var项目)
{
Record.SelectedItems |=(int)项;
}
}
}
}
处理程序:
public class MultipleEnumPickerHandler : ContentHandler
{
public MultipleEnumPickerHandler(IRepository<MultipleEnumPickerRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
}
公共类multipleNumpickerHandler:ContentHandler
{
公共MultipleNumpickerHandler(IRepository存储库)
{
Filters.Add(StorageFilter.For(repository));
}
}
直接还原铁
public class MultipleEnumPickerDriver : ContentPartDriver<MultipleEnumPickerPart>
{
protected override string Prefix { get { return "MultipleEnumPicker"; } }
protected override DriverResult Editor(MultipleEnumPickerPart part, dynamic shapeHelper)
{
return ContentShape("Parts_MultipleEnumPicker_Edit", () => shapeHelper.EditorTemplate(
TemplateName: "Parts/MultipleEnumPicker", Model: part, Prefix: Prefix));
}
protected override DriverResult Editor(MultipleEnumPickerPart part, IUpdateModel updater,
dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
}
<Placement>
<Place Parts_MultipleEnumPicker_Edit="Content:5"/>
</Placement>
@using ModuleNamespace.Models
@model MultipleEnumPickerPart
<fieldset>
<div class="editor-label">@Html.LabelFor(x => x.SelectedItems)</div>
<div class="editor-field">
<select multiple="multiple" id="@Html.FieldIdFor(x => x.SelectedItems)" name="@Html.FieldNameFor(x => x.SelectedItems)">
@foreach (MyEnum item in Enum.GetValues(typeof(MyEnum))) {
var selected = Model.SelectedItems.Contains(item);
<option value="@((int)item)" @if(selected) {<text>selected="selected"</text>}>
@T(item.ToString())
</option>
}
</select>
</div>
</fieldset>