将ESQL转换为LINQ到实体。按相关实体排序

时间:2011-12-09 13:09:21

标签: entity-framework silverlight linq-to-entities ria entity-sql

我正在使用EF + RIA,不幸的是遇到了相关实体排序的一些问题。 出于这个目的,我实现了ESQL查询(仅找到此解决方案):

var queryESQL = string.Format(
@" select VALUE ent from SomeEntities as ent 
   join Attributes as ea ON ea.EntityId = ent.Id 
   where ea.AttributeTypeId = @typeId
   order by ea.{0} {1}", columnName, descending ? "desc" : "asc");

var query = ObjectContext.CreateQuery<SomeEntity>(queryESQL, new ObjectParameter("typeId", attributeTypeId));                                                        

表格有以下结构:

<Attribute>:
    int Id;
    decimal DecimalColumn;
    string StringColumn;
    int EntityId;
    int AttributeTypeId;

<SomeEntity>:
    int Id;
    string Name;  

使用LINQ to Entities方法有没有办法重写这些东西(排序)?

1 个答案:

答案 0 :(得分:2)

这是我的尝试,我不能保证它会起作用。 我需要更多地思考如何获得动态列名,我不确定那个。编辑:您可以使用字符串作为订单列。

int typeId = 1115;
bool orderAscending = false;
string columnName = "StringColumn";
var query = from ent in SomeEntities
join ea in Attributes on ea.EntityId = ent.Id
where ea.AttributeTypeId = typeId;

if(orderAscending)
{
  query = query.OrderBy(ea => columnName).Select(ea => ea.Value);
}
else
{
  query = query.OrderByDescending(ea => columnName).Select(ea => ea.Value);
}

var results = query.ToList(); //调用toList或枚举来执行查询,因为LINQ已延迟执行。

编辑:我认为选择停止后的排序来自于排序。我将select语句移到了order by之后。我还添加了“query =”,但我不确定是否需要。我目前无法对此进行测试。

编辑3:我今天解雇了LINQPad并对我之前的情况进行了一些调整。我使用EF为代码优先方法建模您的数据,它应该接近您所拥有的数据。 如果您只是想获取属性列表(您不是),这种方法会更好。为了解决这个问题,我在MyAttribute类中添加了一个Entity属性。 此代码适用于LINQPAD。

void Main()
{
    // add test entities as needed. I'm assuming you have an Attibutes collection on your Entity based on your tables.
    List<MyEntity> SomeEntities = new List<MyEntity>();
    MyEntity e1 = new MyEntity();
    MyAttribute a1 =  new MyAttribute(){ StringColumn="One", DecimalColumn=25.6M, Id=1, EntityId=1, AttributeTypeId = 1, Entity=e1 };
    e1.Attributes.Add(a1);
    e1.Id = 1;
    e1.Name= "E1";
    SomeEntities.Add(e1);

    MyEntity e2 = new MyEntity();
    MyAttribute a2 = new MyAttribute(){ StringColumn="Two", DecimalColumn=198.7M, Id=2, EntityId=2, AttributeTypeId = 1, Entity=e2 };
    e2.Attributes.Add(a2);
    e2.Id = 2;
    e2.Name = "E2";
    SomeEntities.Add(e2);

    MyEntity e3 = new MyEntity();
    MyAttribute a3 = new MyAttribute(){ StringColumn="Three", DecimalColumn=65.9M, Id=3, EntityId=3, AttributeTypeId = 1, Entity=e3 };
    e3.Attributes.Add(a3);
    e3.Id = 3;
    e3.Name = "E3";
    SomeEntities.Add(e3);

    List<MyAttribute> attributes = new List<MyAttribute>();
    attributes.Add(a1);
    attributes.Add(a2);
    attributes.Add(a3);

    int typeId = 1;
    bool orderAscending = true;
    string columnName = "StringColumn";
    var query = (from ent in SomeEntities
    where ent.Attributes.Any(a => a.AttributeTypeId == typeId)
    select ent.Attributes).SelectMany(a => a).AsQueryable();
    query.Dump("Pre Ordering");
    if(orderAscending)
    {
      // query =  is needed
      query = query.OrderBy(att => MyEntity.GetPropertyValue(att, columnName));
    }
    else
    {
      query = query.OrderByDescending(att => MyEntity.GetPropertyValue(att, columnName));
    }

    // returns a list of MyAttributes. If you need to get a list of attributes, add a MyEntity property to the MyAttribute class and populate it
    var results = query.Select(att => att.Entity).ToList().Dump();
}

// Define other methods and classes here
}
    class MyAttribute
    {
    public int Id { get; set; }
    public decimal DecimalColumn { get; set; }
    public string StringColumn { get; set; }
    public int EntityId { get; set; }
    public int AttributeTypeId { get; set; }
    // having this property will require an Include in EF to return it then query, which is less effecient than the original ObjectQuery< for the question
    public MyEntity Entity { get; set; }

    }
    class MyEntity
    {
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<MyAttribute> Attributes { get; set; }
    public MyEntity()
    {
    this.Attributes = new List<MyAttribute>();
    }

    // this could have been on any class, I stuck it here for ease of use in LINQPad
    // caution reflection may be slow
    public static object GetPropertyValue(object obj, string property)
{
// from Kjetil Watnedal on http://stackoverflow.com/questions/41244/dynamic-linq-orderby
    System.Reflection.PropertyInfo propertyInfo=obj.GetType().GetProperty(property);
    return propertyInfo.GetValue(obj, null);
}