C# 在where条款中是否有访问私有财产的方法?

C# 在where条款中是否有访问私有财产的方法?,c#,linq,entity-framework,domain-driven-design,C#,Linq,Entity Framework,Domain Driven Design,我试图直接将我的域模型映射到EF。为此,我在模型中引入了私有财产,如下所示: private ICollection<Tag> TagsInternal { get; set; } public Article(Guid id, ... , IEnumerable<Tag> tags) : base(id) { ... this.TagsInternal = new List<Tag>(tags.Where(i => i != null))

我试图直接将我的域模型映射到EF。为此,我在模型中引入了私有财产,如下所示:

private ICollection<Tag> TagsInternal { get; set; }

public Article(Guid id, ... , IEnumerable<Tag> tags) : base(id)
{
   ...
   this.TagsInternal = new List<Tag>(tags.Where(i => i != null));
}

public IEnumerable<Tag> Tags { get { return this.TagsInternal.AsEnumerable(); } }
信息是

LINQ to实体中不支持指定的类型成员“标记”。仅支持初始值设定项、实体成员和实体导航属性


有什么办法补救这种情况吗?我正在认真考虑将EF排除在模型之外,然后进行映射,或者按照Vaughn Vernon建议的状态对象路径进行映射。

您说过要将域模型映射到EF。因此,考虑到这一点,您将希望保持EF类尽可能简单。它们的存在只是为了持久化您的域模型。这意味着:

  • 不要将方法放在EF类上
  • 不要使用默认构造函数以外的任何东西
  • 只使用公共方法
  • 手动或使用类似的方法将域类映射到EF类
另外,根据上面的代码,看起来您有自己的UnitOfWork实现。这是不必要的,因为
DbContext
是工作单元。(使用DI容器管理
DbContext
会话。如果这是一个web应用程序,您可能希望它们具有每个请求的生存期。)

我也不知道你为什么返回上面的
也许
。如果找不到,只需返回null。在控制器中,如果
GetArticle()
返回
null
,则从控制器返回
HttpNotFound()

如果执行上述操作,应该可以消除混淆并删除上面的许多映射代码

public static class FluentApiExtensions
{
   public static ManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType> 
      HasMany<TEntityType, TTargetEntityType>(this EntityTypeConfiguration<TEntityType> mapper,
      string propertyName)
      where TEntityType : class
      where TTargetEntityType : class
   {
      var lambda = GetLambdaExpression<TEntityType>(propertyName);

      return mapper
         .HasMany((Expression<Func<TEntityType, ICollection<TTargetEntityType>>>)lambda);
   }

   public static ManyToManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType> 
      WithMany<TEntityType, TTargetEntityType>(this ManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType> mapper,
      string fieldName)
      where TEntityType : class
      where TTargetEntityType : class
   {
      var lambda = GetLambdaExpression<TTargetEntityType>(fieldName);

      return mapper
         .WithMany((Expression<Func<TTargetEntityType, ICollection<TEntityType>>>)lambda);
   }

   private static LambdaExpression GetLambdaExpression<T>(string propertyName)
   {
      var type = typeof (T);
      var parameterExpression = Expression.Parameter(type, "type");
      var expression = (Expression)parameterExpression;

      var propertyInfo = type
         .GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

      if (propertyInfo == null)
         throw new ArgumentException(string.Format("There is no property named '{0}' on type '{1}'.",
            propertyName, type.Name));

      var propertyExpression = Expression.Property(expression, propertyInfo);

      return Expression.Lambda(propertyExpression, parameterExpression);
   }
}
public Maybe<Article> GetArticle(Guid articleId)
{
   articleId.MustNotBeNull();

   var article = this.unitOfWork.Context.Articles
      .Include("TagsInternal")
      .FirstOrDefault(a => a.Id == articleId);

   return article == null
      ? new Maybe<Article>()
      : new Maybe<Article>(article);
}
var test = this.unitOfWork.Context.Articles
   .Where(a => a.Tags.Count() > 0);