2

パラメータを IQueryable.Where に自動生成しようとしています。そのため、エンティティ フレームワーク コードの最初のデータ コンテキストからエンティティを選択でき、多くの面倒なマッピング コードを作成したり接続したりする必要はありません。

私のプロジェクトには、次のような一連の DTO が含まれています。

class FooDto
{
  public string SomeProperty { get; set; }
  public string SomeOtherProperty { get; set; }
}

そして、次のようなエンティティの束:-

class Foo
{
  public string SomeProperty { get; set; }
  public string SomeOtherProperty { get; set; }

  // Some other properties here.
}

DTO には、データベース内のエンティティのサブセットを識別するために必要なフィールドが含まれています。DTO を使用して、エンティティの IQueryable をクエリします。

var result = queryable.Where(
  x => x.SomeProperty == dto.SomeProperty
    && x.SomeOtherProperty == dto.SomeOtherProperty)

実際のプロパティはさまざまですが、クエリは常に「エンティティのすべてのプロパティが DTO の一致するすべてのプロパティと一致する場合」という形になります。これ以上複雑なクエリ オブジェクト機能はありません。

何十もの DTO とエンティティがあります。これらすべての述語を作成/維持し、接続することは、アーキテクチャ上の困難な問題です。現在、戦略パターンを使用しています:-

public class FooDtoSelectStrategy : ISelectStrategy<FooDto, FooEntity>
{
  public Func<FooEntity, bool> GetPredicate(FooDto dto)
  {
    return x => x.SomeProperty == dto.SomeProperty
             && x.SomeOtherProperty == dto.SomeOtherProperty;
  }
}

ninject バインディングの山と一緒ですが、すでに数十個あり、ドメインが拡大するにつれてさらに数百個を検討しています。

AutoMapper を使用して解決した、エンティティから DTO への値のマッピングに関する同様の課題がありました。

オートマッパー (または同様のツール) でこれらの述語を作成して、単一のGenericPredicateProvider<TDto, TEntity>.

4

2 に答える 2

0

あなたがしていることは、実際には仕様パターンと呼ばれます。つまり、基本的にホイールを再設計し、基本的に同じものでわずかに異なるホイールを考え出しました.

T4 テンプレートのようなものを使用して、これらの Predicate プロバイダーを自動生成することもできますが、同じオブジェクトのオブジェクトを照会するのはちょっとばかげているようです。すでにオブジェクトを持っているのに、まったく同じものをすべてのフィールドに照会するのはなぜですか?

于 2012-10-24T17:37:32.620 に答える
0

アップデート:-

これは、AutoMapper の型マッピングを使用して単純なケースを処理する私のプロトタイプです。複雑な型のマッピングなどを処理したい場合は、後でさらに作業が必要になりますが、今のところ、これでうまくいきます。

internal class AutoMapperSelectStrategy<TEntity, TIdentity> :
    IIdentitySelectStrategy<TEntity, TIdentity>
{
    private IMappingEngine mappingEngine;

    internal AutoMapperSelectStrategy(
        IMappingEngine<TEntity, TIdentity> mappingEngine)
    {
        this.mappingEngine = mappingEngine;
    }

    public Expression<Func<TEntity, bool>> GetPredicateForIdentity(
        TIdentity identity)
    {
        var entityParameter = Expression.Parameter(typeof(TEntity));

        var identityScope = Expression.MakeMemberAccess(
            Expression.Constant(
                new ExpressionScope<TIdentity>() { Value = identity }),
                typeof(ExpressionScope<TIdentity>).GetProperty("Value"));

        var equalityExpressions = this.MakeEqualityExpressions(
            identityScope, entityParameter);

        var aggregateEquality = equalityExpressions.Aggregate(
            (x, y) => Expression.AndAlso(x, y));

        var predicate = Expression.Lambda<Func<TEntity, bool>>(
            aggregateEquality, entityParameter);

        return predicate;
    }

    public IEnumerable<BinaryExpression> MakeEqualityExpressions(
        MemberExpression identityScope, ParameterExpression entityParameter)
    {
        var mapExpression =
            mappingEngine.CreateMapExpression<TIdentity, TEntity>();

        var body = mapExpression.Body as MemberInitExpression;
        var bindings = body.Bindings;

        foreach (var binding in bindings.OfType<MemberAssignment>())
        {
            var memberExpression = binding.Expression as MemberExpression;

            var left = Expression.Property(
                identityScope, memberExpression.Member as PropertyInfo);
            var right = Expression.Property(
                entityParameter, binding.Member as PropertyInfo);

            var equalityExpression = Expression.Equal(left, right);

            yield return equalityExpression;
        }
    }

    private class ExpressionScope<TDto>
    {
        public TDto Value { get; set; }
    }
}
于 2012-10-25T11:48:25.490 に答える