gpt4 book ai didi

c# - 构建 Linq2Sql 查询时如何将对象的属性(而不是对象)传递给表达式?

转载 作者:太空宇宙 更新时间:2023-11-03 16:02:01 25 4
gpt4 key购买 nike

tl;dr:我正在寻找一种方法来传递对象的属性 image.Member (而不是对象 image )在构建 Linq2Sql 查询时转换为表达式。这样我就有了Expression<Func<Member, bool>>而不是 Expression<Func<Image, bool>> .


这是我的域模型(如果重要的话是 EF 5):

class Image
{
public string Url { get; set;}
public Member Member { get; set;} // user who uploaded the image
}

class Member
{
public int Id { get; set;}

public bool IsPrivate { get; set;}
public string AboutMe { get; set;}
public string ScreenName { get; set;}

[NotMapped]
public bool IsSearchable
{
get
{
return IsPrivate == false &&
string.IsNullOrEmpty(AboutMe) == false &&
string.IsNullOrEmpty(ScreenName) == false;
}
}
}

接下来,我想使用以下逻辑从数据库中获取所有图像:

if user is logged in, take all his images, and images of all other members who are IsSearchable. If user is not logged in, just take all images of all other members who are IsSearchable.

在 Linq2Objects 中,这看起来像这样:

var images = imagesRepository.All().ToList().AsIEnumerable();

if (this.User == null)
{
images = images.Where(x => x.Member.IsSearchable == true);
}
else
{
var currentMemberId = this.User.Id;
images = images.Where(x => x.Member.IsSearchable == true || x.Member.Id == currentMemberId);
}

当然这是低效的——我不想从数据库中加载 10000 张图片只是为了得到其中的 10 张。这引导我使用 Linq2Sql注意:我知道我可以将逻辑从“IsSearchable”复制到“Where”子句中,我将获得正确的“IQueryable”,但我有 2 个问题:

  1. IsSearchable以后逻辑很容易改变——我永远不会记得这个复制/粘贴
  2. 我将不得不复制它两次(因为 currentMemberId 处于 OR 状态)- 这将使代码难以阅读。

这让我相信我拥有的唯一解决方案是使用 Expression。我们开始吧(感谢 this Expression.Or question ):

var parameterExpression = Expression.Parameter(typeof(Image));

Expression<Func<Image, bool>> memberIsSearchable =
i => i.Member.IsPrivate == false &&
string.IsNullOrEmpty(i.Member.AboutMe) == false &&
string.IsNullOrEmpty(i.Member.ScreenName) == false;

Expression<Func<Image, bool>> memberById =
i => i.Member.MemberId == currentMemberId;

var combined = Expression.Lambda<Func<Image, bool>>(
Expression.Or(
Expression.Invoke(memberIsSearchable, parameterExpression),
Expression.Invoke(memberById, parameterExpression)),
parameterExpression);

var images = imagesRepository.All();

if (this.User == null)
{
images = images.Where(memberIsSearchable);
}
else
{
images = images.Where(combined);
}

这可以很好地转换为 SQL。

问题来了:

有没有可能去掉Image输入表达式定义

Expression<Func<Image, bool>> memberIsSearchable = ...

并将其替换为Member并以某种方式告诉表达式在创建查询时使用“Image”对象中的“Member”:

Expression<Func<Member, bool>> memberIsSearchable = 
m => m.IsPrivate == false &&
string.IsNullOrEmpty(m.AboutMe) == false &&
string.IsNullOrEmpty(m.ScreenName) == false;

images = images.Where(x => memberIsSearchable(x.Member)); // pseudocode

这样做的原因是使 memberIsSearchable表达式通用并在项目的其他部分使用它。

最佳答案

我花了一段时间才弄清楚你的问题到底是什么 - 我想,我现在明白了。

尝试从成员开始(而不是从图像开始)。也许您需要引入额外的导航属性:

Expression<Func<Member, bool>> IsSearchable =  member => !member.IsPrivate
&& !String.IsNullOrEmpty(member.AboutMe)
&& !String.IsNullOrEmpty(member.ScreenName);

Member currentUser = null;
using (var container = new /**/())
{
var images = container.Members.Where(IsSearchable).SelectMany(member => member.Images);
if (currentUser != null)
images = images.Concat(currentUser.Images);

var result = images.ToArray();
}

关于c# - 构建 Linq2Sql 查询时如何将对象的属性(而不是对象)传递给表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20940101/

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