我正忙着实现一个返回设备列表的api控制器,
这是我目前的帮助方法:
private List<Device> GetUsersDevices(string userName)
{
int userId = -1;
List<Device> myDevices;
if (Int32.TryParse(User.Identity.Name, out userId))
{
myDevices = db.Devices.Where((x => x.EndUserId == userId && x.Deleted == false)).OrderByDescending(x => x.LastComms).ToList();
return myDevices;
}
return null;
}
现在这一切都很好,但我现在需要添加一条规则,它只返回某些设备(一个与终端客户端兼容)
所以我想列出一个终端客户端允许的设备类型列表,如下面的伪代码:
List endclient1 = device type 1, device type 2 etc.
List endclient2 = device type 2, device type 5 etc.
但是我想过滤我的设备列表以删除所有不支持的设备。现在我明白我可以继续在原始语句中添加.Where(...)子句,但我想知道最有效的方法,并且如果设备类型的数量增长它维护那行代码并不是很容易。我可能希望为不同的终端客户端提供不同的受支持设备列表,所以如果我可以通过允许的设备列表进行过滤,它将允许我有一个控制器为所有不同的终端客户端提供服务,它只会返回什么设备他们被允许。
可能需要的其他信息。
这是MyDevice类
public class MyDevice
{
public MyDevice(long deviceId, string name, string serialNo, string deviceType, int deviceTypeId, bool enabled)
{
this.deviceId = deviceId;
this.name = name;
this.serialNo = serialNo;
this.deviceTypeName = deviceType;
this.deviceTypeId = deviceTypeId;
this.enabled = enabled;
}
public string name { get; set; }
public long deviceId { get; set; }
public string serialNo { get; set; }
public string deviceTypeName { get; set; }
public int deviceTypeId { get; set; }
public bool enabled { get; set; }
}
答案 0 :(得分:1)
如果我理解你的问题,你想做这样的事情:
var allowedDeviceTypes = GetAllowedDeviceTypesForUser(userId);
return db.Devices
.Where(x => x.EndUserId == userId && x.Deleted == false)
.Where(x => allowedDeviceTypes.Contains(x.deviceTypeId))
.OrderByDescending(x => x.LastComms)
.ToList();
这将转换为WHERE deviceTypeId IN (...)
子句(假设您正在使用LINQ to SQL,Entity Framework或NHibernate),这对于合理数量的设备类型来说足够有效。
请注意,方法GetAllowedDeviceTypesForUser
与LINQ无关,您可以根据需要随意实施(例如,将其委托给其他服务,添加自定义规则等)。只要您有获取允许的设备类型列表的方法,就可以将其传递给LINQ查询。
这是一个微不足道的实施:
private IDictionary<int, IList<int>> _allowedDeviceTypesPerUserId =
new Dictionary<int, IList<int>>() {
{ 1, new[] { 1, 2 } },
{ 2, new[] { 2, 5 } },
// ...
};
private IList<int> GetAllowedDeviceTypesForUser(int uesrId)
{
return _allowedDeviceTypesPerUserId[userId];
}
这假设每个用户允许的设备列表是静态的。如果它是动态的,你必须从某个地方加载它,在这种情况下你也可以考虑使用Join
,但我不确定这是最好的主意在你的情况下。
答案 1 :(得分:0)
您可以查看join,根据密钥(“{1}}”为您提供“所有设备”列表和“兼容设备”列表的交集。
在这种情况下,你会做类似的事情(没有检查语法正确性):
deviceId
这只是我的头脑,所以可能会有一些错误,但你应该能够弄清楚如何使用它。
答案 2 :(得分:0)
除非你有几十亿台设备,否则我认为你发现普通的旧LINQ效率不高:
myDevices = from device in db.Devices
where device.EndUserId == userId
&& device.Deleted == false
&& allowedTypes.Contains(device.Type)
order by device.LastComms
select device;
它也是最具可读性和可维护性的!
另一个优点是标准LINQ是编译器抖动转换为SQL可以全部优化这个标准的东西 - 你测量它的速度 - 它是一个问题,你把它与替代品进行比较?
答案 3 :(得分:0)
我不确定我理解你的问题。但我会这样做:
int userId = -1;
List<Device> myDevices;
if (Int32.TryParse(User.Identity.Name, out userId))
{
myDevices = db.Devices.Where((x => x.EndUserId == userId && x.Deleted == false)).OrderByDescending(x => x.LastComms).ToList();
var result1 = myDevices.Where(x=>x.name==someName);
var result2 = myDevices.Where(x=>x.deviceId >someDeviceId );
var result3 = myDevices.Where(x=>x.serialNo.Contains("someSerialNo"));
....
return resultN.ToList();
}
或
myDevices = from item in db.Devices
where item.name == someName && item.deviceId == someDeviceId && ...
where ...
OrderByDescending item.LastComms
select item;