我有一个包含参数列表的类。例如:
public class Container
{
public List<Parameter> Parameters { get; set; }
}
public class Parameter
{
puplic string Name {get; set;}
}
通过实体框架从数据库获取的类Сontainer。许多类包含Container。我需要确保包含Сontainer的所有类,并从包含Parameters的排序列表的数据库中检索。也就是说,Container必须对参数或请求步骤进行排序,或者之后立即对其进 如何实现这一目标? 也许写入配置
internal class ContainerConfiguration : EntityTypeConfiguration<Container>
{
public ContainerConfiguration()
{
ToTable("Container");
HasKey(p => p.Id);
... ???
}
}
或者在数据集中怀疑
protected override IQueryable<Container> DataSet(DbContext db)
{
return db.Set<ProcessMeasurer>()
.Include(it => it.Parameters.Select(p => p.Parameter));
}
答案 0 :(得分:0)
解决问题的另一个选择:
创建属性并指定默认情况下用于排序的字段:
public class DefaultOrderFieldAttribute : Attribute
{
public DefaultOrderFieldAttribute()
{
}
public string FieldName { get; set; }
}
[DefaultOrderField(FieldName = "ParameterName")]
public partial class Parameter
{
}
写一个访客,在检测到我们的属性的情况下修改选择:
public class DefaultOrderVisitor : DefaultExpressionVisitor
{
public override DbExpression Visit(DbScanExpression expression)
{
const string NAMESPACE = "OrderTest";
var type =
Assembly.GetExecutingAssembly().GetType(string.Format("{0}.{1}", NAMESPACE, expression.Target.Name));
var attribute =
type.GetCustomAttributes(typeof (DefaultOrderFieldAttribute)).SingleOrDefault() as
DefaultOrderFieldAttribute;
if (attribute != null)
return expression.OrderBy(ex => ex.Property(attribute.FieldName));
return expression;
}
}
加入我们的访客拦截器:
public class DefaultOrderInterceptor : IDbCommandTreeInterceptor
{
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
{
var queryCommand = interceptionContext.Result as DbQueryCommandTree;
if (queryCommand != null)
{
var newQuery = queryCommand.Query.Accept(new DefaultOrderVisitor());
interceptionContext.Result = new DbQueryCommandTree(queryCommand.MetadataWorkspace,
queryCommand.DataSpace, newQuery);
}
}
}
}
并在配置中注册(此类只需与模型位于同一个程序集中):
public class EntityFrameworkConfiguration : DbConfiguration
{
public EntityFrameworkConfiguration()
{
AddInterceptor(new DefaultOrderInterceptor());
}
}
答案 1 :(得分:-1)
需要使用实体类。 如果我们想要对包含它的所有元素进行排序,我们必须更改相应的属性。 明显的变体 - 创建属性设置器。
private List<Parameter> _parameters;
public List<Parameter> Parameters
{
get { return _parameters; }
set { _parameters = value.OrderBy(...).ToList();
}
但是编译器的行为(调用setter一次,并且多次调用getter)让我有理由假设目标集合不是一次性放入属性中。查询中的项目将逐渐添加到集合中。因此,在setter中排序并不总是有效。 因此,我们必须对返回值进行排序
get
{
if(_parameters == null) return null;
_parameters = _parameters.OrderBy(...).ToList();
return _parameters;
}
有效。但问题是,当EntityFramework插入每个值时,将对getter进行吸引,从而进行排序。这会影响性能。
目前我所知道的最好的变体是使用函数Prepare继承接口中的所有实体
public interface IEntity
{
void Prepare();
}
并在每个类模型中实现它。包含其他模型的模型会为每个所需的属性生成一种方法。
public class SomeModel : IEntity
{
public CustomType SomeProperty { get; set; }
public OneMoreCustomType AnotherProrerty { get; set; }
public void Prepare()
{
SomeProperty.Prepare();
AnotherProperty.Prepare();
}
}
对于相应的课程,将采取适当的行动。包括排序。 Сall在使用之前准备Сontainer(在本例中)的方法。 例如,在业务逻辑(MVPVM)中。