2

私は最初にコードを使用して、リストプロパティで簡単なクエリを実行して、フィルタリングリストに文字列が含まれているかどうかを確認しようとしています。しかし、私は問題にぶつかっています。簡単にするために、次のことを想定します。

public class Person
{
   public List<string> FavoriteColors { get; set; }
}

//Now some code. Create and add to DbContext
var person = new Person{ FavoriteColors = new List<string>{ "Green", "Blue"} };
dbContext.Persons.Add(person);
myDataBaseContext.SaveChanges();

//Build 
var filterBy = new List<string>{ "Purple", "Green" };
var matches = dbContext.Persons.AsQueryable();
matches = from p in matches
          from color in p.FavoriteColors 
          where filterBy.Contains(color)
          select p;

私が検討しているオプションは、FavoriteColorsが文字列の場合、Contains呼び出しを実行できるため、これをjsonシリアル化文字列に変換することです。または、船外に出て「カラー」エンティティを作成することもできますが、かなり重いです。残念ながら、列挙型もサポートされていません。

4

2 に答える 2

1

問題はコレクションではなく、への参照だと思いますmatches

var matches = dbContext.Persons.AsQueryable();
matches = from p in matches
          from color in p.FavoriteColors 
          where filterBy.Contains(color)
          select p;

EF4の既知の問題と考慮事項を確認すると、これは多かれ少なかれ前述のケースとまったく同じです。

クエリでのエンティティなどの非スカラー変数の参照はサポートされていません。このようなクエリが実行されると、NotSupportedException 例外がスローされ、「型 EntityType の定数値を作成できません。

また、スカラー変数のコレクションの参照がサポートされていることが明確に示されていることにも注意してください(これは EF 4 imo の新機能です)。

以下はうまくいくはずだと言っています(今は試すことができません):

matches = from p in dbContext.Persons
          from color in p.FavoriteColors 
          where filterBy.Contains(color)
          select p;
于 2011-02-18T04:28:56.830 に答える
0

この制限を克服するために「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");
            });
    }
}

...すべてがいくつかのテストで完全に機能しているように見えましたが(重いですが)、MVC3 ビューの Multiselect ListBox という本来の目的のために実装しました。理由は不明ですが、ListBox にエンティティ コレクション プロパティと同じ名前が割り当てられている場合、選択した項目は読み込まれません。

以下が機能しなかったことを実証するには: //Razor View Code

string[] animalOptions = new string[] {"Dog", "Cat", "Goat"};
string[] animalSelections = new string[] {"Dog", "Cat"};
Html.ListBox("Animals", Multiselect(animalOptions, animalSelections));

この制限を回避するには、次の 4 つのことを行う必要がありました。

//#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 ());

プロパティが文字列のリストの場合、リストボックスのバグは発生しなかったことに注意してください。エンティティのリストの場合は、それが気に入らなかっただけです。

于 2011-02-19T02:47:01.807 に答える