重用包含相同属性但不同lambda where子句条件的方法

时间:2018-01-26 09:50:18

标签: c# entity-framework linq lambda

以下是示例场景,我有3种不同的参数,但是结果与属性类的返回列表相同。

以下是我的代码:

// My Model class:
public class Users{ 
   public string Name{ get; set; }
   public int Age { get; set; }
   public string Location { get; set; }
}

// My Vm class:
public class UserVm { 
   public string Name{ get; set; }
   public int Age { get; set; }
   public string Location { get; set; }
}

这是我的lambda查询

// by name
public IEnumerable<UserVm> GetUsersByName (string name){
      return db.Users.Where(x=>x.Name == name).Select(users=>new UserVm{
          Name = users.Name,
          Age = users.Age,
          Location = users.Location
      }).Tolist();
}

// by location
public IEnumerable<UserVm> GetUsersByAge (int age){
      return db.Users.Where(x=>x.Age == age).Select(users=>new UserVm{
          Name = users.Name,
          Age = users.Age,
          Location = users.Location
      }).Tolist();
}

// by age
public IEnumerable<UserVm> GetUsersByLocation (string location){
      return db.Users.Where(x=>x.Location== location).Select(users=>new UserVm{
          Name = users.Name,
          Age = users.Age,
          Location = users.Location
      }).Tolist();
}

正如您所注意到的,它们都在视图模型中返回相同的结果。有没有像我可以重用那些冗余代码的方法?就像我会把这些代码

return db.Users.Where(x=>x.Location== location).Select(users=>new Users{
          Name = users.Name,
          Age = users.Age,
          Location = users.Location
      }).Tolist();

在一个方法中,但是在调用main方法的每个方法中where子句都不同?

4 个答案:

答案 0 :(得分:6)

只需将lambda表达式作为Func<Users, bool>传递给您的查询:

public IEnumerable<UserVm> GetUsers(Func<Users, bool> predicate)
{
      return db.Users.Where(predicate).Select(users=>new UserVm
      {
          Name = users.Name,
          Age = users.Age,
          Location = users.Location
      });
}

另请注意,我已从原始代码中删除了ToList(),因为无论如何您都要返回IEnumerable

你这样使用它:

// To get all users under a specific age
var usersVm = GetUsers(u => u.Age < age);

// To get all users with a specific name
var usersVm = GetUsers(u => u.name == name);
BTW:我喜欢在ViewModel类中有一个构造函数,它是Model类的一个实例,所以我可能会这样写:

public class UserVm { 
   public UserVm (Users model)
   {
       Name = model.Name;
       Age = model.Age;
       Location = model.Location;
   }
   public string Name{ get; set; }
   public int Age { get; set; }
   public string Location { get; set; }
}

然后你的GetUsers方法看起来像这样:

public IEnumerable<UserVm> GetUsers(Func<Users, bool> predicate)
{
      return db.Users.Where(predicate).Select(user => 
          new UserVm(user));
}

答案 1 :(得分:3)

您可以做的一件简单的事情是在扩展方法中移动UserVm对象,并且不再重复对象初始化。

#!/bin/bash

[... other bash code here ...]

SCRIPT='/path/to/script/to/run/remotely.sh'
LOGIN='test'
IP='your ip or hostname'
LOCATION='/destination/path/to/script/to/run/remotely.sh'

### start expect part here, you may add '-d' after 'expect' for debug

/usr/bin/expect << EOD
### set a 3 minute timeout
set timeout 180
### copy the script you wish to run on the remote machine
spawn scp -o StrictHostKeyChecking=no -p $SCRIPT $LOGIN@$IP:$LOCATION
expect {
  timeout            { send_user "\n# TIMED OUT. HOST NOT REACHABLE #\n"; exit 3 }
  "*assword: "
}
send "your_password\r"
expect {
  "*assword: " { send_user "\n# Incorrect Password. Login Failed. #\n"; exit 4 }
  "100%" { send_user "\nFile copied\n" }
}

### ssh to remote server to run script
spawn ssh $LOGIN@$IP
expect {
  timeout        { send_user "\n# TIMED OUT. SSH DAEMON or PORT 22 CLOSED #\n"; exit 6 }
  "*assword: "
}
send "your_password\r"
expect {
  timeout        { send_user "\n# TIMED OUT. PROMPT NOT RECOGNISED! #\n"; exit 7 }
### expect the prompt symbol
  -re {[#>$] }
## execute your script on the remote machine
send "$LOCATION\r"
expect {
  "enter what you expect here" { send_user "\nRESULT: Message based on what you set the expect to read $IP\n" }
  -re {[#>$] }
}

[... other expect code here ... ]

### exit remote ssh session
send "exit\r"
### end of expect part of script 
EOD
### continue bash script here

[... other bash code here ...]

答案 2 :(得分:1)

创建一个新方法:

public List<Users> GetUsers(object vmData)
{
   vmData.Select(users=>new Users{
          Name = users.Name,
          Age = users.Age,
          Location = users.Location
      }).Tolist();
}

答案 3 :(得分:1)

您可以为过滤制作不同的扩展方法。

public static IEnumerable<UserVm> FilterByName(this IEnumerable<UserVm> query, string name)
{
    return query.Where(x => x.Name == name);
}

并转换为Users对象:

public static IEnumerable<Users> ToUsers(this IEnumerable<UserVm> query)
{
    return query.Select(users => new Users{
        Name = users.Name,
        Age = users.Age, 
        Location = users.Location
    });
}

允许你这样称呼它:

var usersA = db.Users.FilterByName("A").ToUsers().ToList();

可在此fiddle中找到此示例。