gpt4 book ai didi

c# - 如何同时从两个不同的列执行 OrderBy,而不是使用 ThenBy

转载 作者:太空宇宙 更新时间:2023-11-03 13:37:06 31 4
gpt4 key购买 nike

我有一个独特的情况,我试图在 IQueryable 上执行 .OrderBy。 (如果我的定义不准确,请原谅我)

我有以下内容:

IQueryable<Source> data = e.Sources.Where(element => element.IsActive == true).OrderBy(el => el.SourceEntityKey);
if (sortDesc.SortDirection == ListSortDirection.Ascending)
{
data = data.OrderBy(order => order.EntityBase.EntityName);
}
else
{
data = data.OrderByDescending(order => order.EntityBase.EntityName);
}

问题是,我不能这样做,因为这不是实际存储在数据库中的值,因此 LINQ to Entities 不支持它。来源实际上是人员和公司的列表。作为来源,他们可以有一个子类型作为个人或公司。如果他们是一家公司,它有自己的表来存储公司名称。如果是一个人,它有自己的表,有两列存储名字和姓氏。因此,不知何故,我需要一种方法来按名称对它们进行排序,即使名称在数据库中的存储方式不同。真正的值(value)是这样的:

 EntityBase.Person.FirstName
EntityBase.Person.LastName
EntityBase.Company.CompanyName

另一个问题是我还不能枚举列表,因为在这之后还有更多的执行。所以我需要一种方法在枚举到列表之前完成此操作。

感谢您的帮助

编辑:

我试图简化以希望让事情变得更容易......这是我的模型,不相关的修剪掉了。

实体库:

[MetadataType(typeof(EntityBaseMetaData))]
public partial class EntityBase
{
[IgnoreDataMember]
public Person AsPerson
{
get
{
Person p = new Person();
try
{
p = (Person)this;
}
catch
{
p = null;
}
return p;
}
}

[IgnoreDataMember]
public Company AsCompany
{
get
{
Company c = new Company();
try
{
c = (Company)this;
}
catch
{
c = null;
}
return c;
}
}

[IgnoreDataMember]
public string EntityName
{
get
{
string name = "";
if (this.AsPerson != null)
{
name = this.AsPerson.FirstName + " " + this.AsPerson.LastName;
}
else if (this.AsCompany != null)
{
name = this.AsCompany.CompanyName;
}

return name;
}
}
}

public class EntityBaseMetaData
{
//[ScaffoldColumn(false)]
public object EntityBaseKey { get; set; }
}

人:

[MetadataType(typeof(PersonMetaData))]
public partial class Person
{
}

public class PersonMetaData
{
[DisplayName("Person ID")]
public object EntityBaseKey { get; set; }

[DisplayName("First Name")]
public object FirstName { get; set; }

[DisplayName("Last Name")]
public object LastName { get; set; }
}

公司:

[MetadataType(typeof(CompanyMetaData))]
public partial class Company
{
}

public class CompanyMetaData
{
[DisplayName("Company ID")]
public object EntityBaseKey { get; set; }

[DisplayName("Company Name")]
public object CompanyName { get; set; }

}

来源:

[MetadataType(typeof(SourceMetaData))]
public partial class Source
{ }

public class SourceMetaData
{
[DisplayName("Source ID")]
public object EntityBaseKey { get; set; }
}

Controller Action :

[GridAction(EnableCustomBinding = true)]
public ActionResult Read(GridCommand command)
{
Entities e = new Entities();
IQueryable<Source> data = e.Sources.Where(element => element.IsActive == true).OrderBy(el => el.EntityBaseKey);

int count = data.Count();

//Apply Grid Commands
if (command != null)
{
//Apply data sort
foreach (SortDescriptor sortDesc in command.SortDescriptors)
{
switch (sortDesc.Member)
{
case "SourceName":
if (sortDesc.SortDirection == ListSortDirection.Ascending)
{
data = data.OrderBy(order => order.EntityBase.EntityName);
}
else {
data = data.OrderByDescending(order => order.EntityBase.EntityName);

}
break;
}
}

//Apply paging
if (command.PageSize > 0)
{
data = data.Skip((command.Page - 1) * command.PageSize).Take(command.PageSize);
}

}

List<SourceView> sources = new List<SourceView>();

foreach (Source s in data.ToList())
{
sources.Add(new SourceView
{
EntityBaseKey = s.EntityBaseKey,
SourceName = s.EntityBase.EntityName,
});
}

return View(new GridModel
{
Data = sources,
Total = count
});
}

这就是我希望它的工作方式。此外,还有更多未显示的过滤和排序。网格命令内容用于 Telerik 网格,来自 Telerik Extensions for ASP.Net。如果我们不必进行客户端绑定(bind)会容易得多,但是数据库信息太多,因此服务器端绑定(bind)的性能会受到严重影响。

非常感谢您的帮助。

最佳答案

您可以尝试定义辅助类型并使用联合。我定义了一个具有两个子类型的客户类型:公司和个人:

private static void OrderingTest()
{
Database.SetInitializer(new DropCreateDatabaseAlways<Test1Context>());
var context = new TestContext();

context.Customers.Add(new Company { Denomination = "A" });
context.Customers.Add(new Company { Denomination = "C" });
context.Customers.Add(new Person { LastName = "B" });
context.Customers.Add(new Person { LastName = "D" });
context.SaveChanges();

var a = (from customer in context.Customers.OfType<Company>()
select new CustomerInfo { Name = customer.Denomination, Customer = customer }
)
.Union
(from customer in context.Customers.OfType<Person>()
select new CustomerInfo { Name = customer.LastName, Customer = customer }
);
var customerInfoList = a.OrderBy(item => item.Name);
var customers = customerInfoList.ToList().Select(item => item.Customer);
}

class CustomerInfo
{
public string Name { get; set; }
public Customer Customer { get; set; }
}

编辑:

一些观察:

-添加的两个属性如果这样重写会更简单:

public Person AsPerson
{
get
{
return this as Person;
}
}

-记得在 Controller 中删除 ToList:

case "SourceName":                            
List<Source> sources = data.ToList();

如果您希望在数据库上进行跳转。

这是我的猜测:

我仍然不明白 Source 实体的用途,但我的建议是向 EntityBase 添加一个名为 Source 的反向属性,以便你可以替换:

IQueryable<Source> data = e.Sources.Where(element => element.IsActive == true).OrderBy(el => el.EntityBaseKey);

与:

IQueryable<EntityBase> data = e.Entities.Where(entityBase => entityBase.Source.IsActive).OrderBy(entityBase => entityBase.Source.EntityBaseKey);

一旦您的集合是 EntityBase 的集合,您应该能够使用以下内容进行查询:

  var entities = (from entity in data.OfType<Company>()
select new EntityBaseInfo { Name = entity.CompanyName, EntityBase = entity }
)
.Union
(from entity in data.OfType<Person>()
select new EntityBaseInfo { Name = entity.FirstName + " " + entity.LastName, EntityBase = entity }
);
var orderedEntities = entities.OrderBy(item => item.Name).Select(item => item.EntityBase);

然后您可以应用 skip 和 take,最后当您需要创建 SourceView 时,您可以使用:

foreach (EntityBase entity in orderedEntities.ToList())
{
sources.Add(new SourceView
{
EntityBaseKey = entity.Source.EntityBaseKey,
SourceName = entity.EntityName,
});
}

我不太明白 Source.EntityBaseKey 代表什么,因为我错过了完整的代码。我只是试图修改发布的代码以便能够使用联合。希望有用。

关于c# - 如何同时从两个不同的列执行 OrderBy,而不是使用 ThenBy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18346431/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com