C# 在where条款中是否有访问私有财产的方法?
我试图直接将我的域模型映射到EF。为此,我在模型中引入了私有财产,如下所示: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))
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类
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);