我有一个包含三列的表格。两列组成了PK。该表存储有关目录中文件的信息。
我有一个文件目录作为我的输入。
目标是获取添加的文件列表和删除的文件列表。
我有以下代码:
string uri = "ftp://ftp.myftpsite.com/files";
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(uri);
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
StreamReader streamReader = new StreamReader(response.GetResponseStream());
using (myEntities context = new myEntities())
{
IQueryable<ITEM> storedItems = from item in context.ITEMs where item.YEAR == "2013" select item;
List<ITEM> currentItemList = new List<ITEM>();
string line = streamReader.ReadLine();
while (!string.IsNullOrEmpty(line) && line.EndsWith(".htm"))
{
ITEM item = new ITEM();
item.YEAR = line.Substring(0,4);
item.NUM = line.Substring(7,5);
currentItemList.Add(item);
line = streamReader.ReadLine();
}
IQueryable<ITEM> currentItems = currentItemList.AsQueryable<ITEM>();
IQueryable<ITEM> newItems = from item in currentItems where !(from storedItem in storedItems select storedItem.YEAR + storedItem.NUM).Contains(item.YEAR + item.NUM) select item;
IQueryable<ITEMS> removedItems = from item in storedItems where !(from currentItem in currentItems select currentItem.YEAR + currentItem.NUM).Contains(item.YEAR + item.NUM) select item;
List<ITEM> newItemsList = newItems.ToList();
List<ITEM> removedItemsList = removedItems.ToList();
}
最后newItems
应该是ftp站点上的项目,而不是数据库,removedItems
应该是数据库中的项目,而不是ftp站点上的项目。
newItems
有效,但以下行会返回错误:
List<ITEM> removedItemsList = removedItems.ToList();
错误是:
System.NotSupportedException:无法创建常量值 输入'MYProject.ITEM'。只有原始类型或枚举 在这种情况下支持类型。
我认为我的第二个LINQ查询出了问题,但我不确定是什么。
此外,性能很重要,因此欢迎有关性能的建议。
当前解决方案:
List<string> criteria = (from item in currentItemList select item.YEAR + item.NUM).ToList();
foreach(AMENDMENT a in storedItems)
{
if(!criteria.Contains(a.YEAR + a.NUM))
//do stuff here
}
所以基本上不是在LINQ中执行条件语句,而是在for循环中的if语句中完成它。老实说,我认为这很难看,但它有两个好处。
有效
而不是像LINQ查询一样花费大约3秒钟,它需要几百分之一秒。
答案 0 :(得分:1)
你先尝试投射吗?如果您的数据大小不是太极端,它不会杀死您。否则你需要更有创意。
IQueryable<ITEMS> removedItems = from item in storedItems.ToList() where !(from currentItem in currentItems select currentItem.YEAR + currentItem.NUM).Contains(item.YEAR + item.NUM) select item;
你的查询很奇怪。另一种方式可行,但我没有审查。你已经在2013年进行了分组,所以这也是如此。
List<int> itemNumbers = currentItems.Where(x=>x.YEAR ==2013).Select(x=>x.NUM).ToList();
IQueryable<ITEMS> removedItems = from item in storedItems where !itemNumbers.Contains(item.NUM) select item;
答案 1 :(得分:0)
尝试这样的事情:
using (myEntities context = new myEntities())
{
List<ITEM> storedItems = (
from item in context.ITEMs
where item.YEAR == "2013"
select item ).ToList();
List<ITEM> currentItemList = new List<ITEM>();
string line = streamReader.ReadLine();
while (!string.IsNullOrEmpty(line) && line.EndsWith(".htm"))
{
ITEM item = new ITEM();
item.YEAR = line.Substring(0,4);
item.NUM = line.Substring(7,5);
currentItemList.Add(item);
line = streamReader.ReadLine();
}
List<ITEM> newItemsList = (
from cItem in currentItems
join sItem in storedItems
on ( cItem.YEAR + cItem.NUM ) equals ( sItem.YEAR + sItem.NUM )
into g
from gItem in g.DefaultIfEmpty()
where gItem == null
select cItem ).ToList();
List<ITEM> removedItemsList = (
from sItem in storedItems
join cItem in currentItems
on ( sItem.YEAR + sItem.NUM ) equals ( cItem.YEAR + cItem.NUM )
into g
from gItem in g.DefaultIfEmpty()
where gItem == null
select sItem ).ToList();
}
答案 2 :(得分:0)
当前解决方案:
List<string> criteria = (from item in currentItemList select item.YEAR + item.NUM).ToList();
foreach(AMENDMENT a in storedItems)
{
if(!criteria.Contains(a.YEAR + a.NUM))
//do stuff here
}
所以基本上不是在LINQ中执行条件语句,而是在for循环中的if语句中完成它。老实说,我认为这很难看,但它有两个好处。
有效
而不是像LINQ查询一样花费大约3秒钟,它需要几百分之一秒。
如果其他人有建议,我仍然愿意接受。