Я решил поэкспериментировать, создав класс «StringEntity», чтобы преодолеть это ограничение, и использовал неявные операторы для удобного преобразования строк и в строки.См. Ниже решение:
public class MyClass
{
[Key, DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid Id { get; set; }
public List<StringEntity> Animals { get; set; }
public MyClass()
{
List<StringEntity> Animals = List<StringEntity>();
}
}
public class StringEntity
{
[Key, DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid Id { get; set; }
public string Value { get; set; }
public StringEntity(string value) { Value = value; }
public static implicit operator string(StringEntity se) { return se.Value; }
public static implicit operator StringEntity(string value) { return new StringEntity(value); }
}
public class MyDbContext : DbContext
{
public DbSet<MyClass> MyClasses { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyClass>()
.HasMany(x => x.Animals)
.WithMany()
.Map(x =>
{
x.MapLeftKey(l => l.Id, "MyClassId");
x.MapRightKey(r => r.Id, "StringEntityId");
});
}
}
... Все выглядело так, как будто оно отлично работало с некоторым тестированием (хотя и тяжелым), а затем я реализовал для своей первоначальной цели Multiselect ListBox в виде MVC3.По неизвестным мне причинам, если для ListBox назначено то же имя, что и для свойства Entity Collection, ни один из выбранных вами элементов не будет загружен.
Чтобы продемонстрировать следующее НЕ работает: // Razor View Code
string[] animalOptions = new string[] {"Dog", "Cat", "Goat"};
string[] animalSelections = new string[] {"Dog", "Cat"};
Html.ListBox("Animals", Multiselect(animalOptions, animalSelections));
Чтобы обойти это ограничение, мне нужно было сделать четыре вещи:
//#1 Unpluralize the ListBox name so that is doesn't match the name Model.Animals
var animalOptions = new string[] {"Dog", "Cat", "Goat"};
@Html.ListBox("Animal", new MultiSelectList(animalOptions, Model.Animals.Select(x => x.Value)))
//#2 Use JQuery to replace the id and name attribute, so that binding can occur on the form post
<script type="text/javascript">
jQuery(function ($) {
$("select#Animal").attr("name", "Animals").attr("id", "Animals");
});
</script>
//#3 Create a model binder class to handle List<StringEntity> objects
public class StringEntityListBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var stringArray = controllerContext.HttpContext.Request.Params.GetValues(bindingContext.ModelName);
return stringArray.Select(x => new StringEntity(x)).ToList();
}
}
//#4 Initialize the binder in your Global.asax setup.
ModelBinders.Binders.Add(typeof(List<StringEntity>), new StringEntityListBinder ());
Обратите внимание, что ошибка Listbox НЕ возникала, когда свойство представляло собой список строк, ему просто не нравилось, когда оно представляло собой список объектов.