在查询中将类型从匿名转换为其他类型——需要保留 try/catch 块的范围



编辑 -- 我真的很想得到一些反馈,为什么这个问题被否决了? 我给出了一个工作和非工作版本的代码,展示了我尝试过的所有内容,并迅速响应了建议。 也许你们中的一些人已经忘记了,当代表的每一点都很重要时,开始时爬得有多慢!

我愿意改进问题标题。 在 C#6 中

以下代码有效:

DistributionStopInformation stop = new DistributionStopInformation();
stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select s).First();

但是一旦我不想返回所有内容,我就会收到错误:Cannot implicitly convert type <anonymous....

这样:

DistributionStopInformation stop = new DistributionStopInformation();
stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
createdby = s.CreatedBy
}).First();

我尝试创建一个新类并从基类继承,例如:

class stopInfo : DistributionStopInformation
{
}
stopInfo stop = new stopInfo();
stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
createdby = s.CreatedBy
}).First();

但是我得到了同样的错误。

在转向这里寻求帮助之前尝试了几种不同的事情......

编辑: 我需要这样做的原因是我需要像这样将其包装在 try/catch 块中——显然 newItem 行将尝试访问范围之外的停止变量。

try
{
var stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
createdby = s.CreatedBy
}).First();
}
catch (Exception)
{
throw;
}
newItem.CreatedBy = stop.CreatedBy

编辑: 好的,根据请求,这里是完整的代码 - 在下面的停止超出了下面的范围:

foreach (var item in newItems)
{
//go see if this item exists already
var itemCheck = (from i in aDb.recent_items where i.item_number == item.ItemNumber select i).ToArray();
if (itemCheck.Count() == 0)
{
//go get the stop
try
{
stopInfo stop = new stopInfo();
var stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
s.BranchId,
s.RouteCode,
s.StopName,
s.StopAddress,
s.StopCity,
s.StopState,
s.StopZipPostalCode,
}).First();
}
catch (Exception)
{
throw;
}
//update the counter which will be returned            
itemCountUpdated++;
//give em some info so we know its still working...
Console.WriteLine("Doing number: " + itemCountUpdated);
//create a new item
recent_items newItem = new recent_items();
//grab the info for each property
newItem.azure_record_created = DateTime.Now;
newItem.branch_id = stop.BranchId;
newItem.datatrac_record_created = item.DatetimeCreated;
if (stop.RouteCode.Length >= 3) { newItem.branch_id_from_route_code = stop.RouteCode.ToString().Substring(0, 3); }
newItem.datatrac_unique_id_no = item.UniqueIdNo;
newItem.item_description = item.ItemDescription;
newItem.item_number = item.ItemNumber;
newItem.item_sequence = item.ItemSequenceNo;
newItem.item_weight = item.ExpectedWeight;
newItem.route_code = stop.RouteCode;
newItem.stop_address = stop.StopAddress;
newItem.stop_city = stop.StopCity;
newItem.stop_name = stop.StopName;
newItem.stop_state = stop.StopState;
newItem.stop_zipcode = stop.StopZipPostalCode;
//add the record to the context
aDb.recent_items.Add(newItem);
//if this is the 100th time then write the records
if (itemCountUpdated % 100 == 0)
{
aDb.SaveChanges();
}
}
}
//write out any records that are still left
aDb.SaveChanges();

每个建议尝试了相同的错误:

var stop = new { branchID = "tst" };
try
{
//stopInfo stop = new stopInfo();
stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
s.BranchId,
}).First();
}
catch (Exception)
{
throw;
}

根据另一个建议,我也尝试过:

try
{
//stopInfo stop = new stopInfo();
DistributionStopInformation stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new DistributionStopInformation
{
s.BranchId,
}).First();
}
catch (Exception)
{
throw;
}

但我得到一个:

无法使用集合初始值设定项初始化类型"stopInfoClass",因为它不实现"System.Collections.IEnumerable">

如果您必须仅保留一个属性的 anon 类型,请尝试此操作,尽管您将无法将stop变量传递给其他方法,因为它是 anon 类型

var stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
createdby = s.CreatedBy
}).First();

对于您的特定问题,您可以完全删除 try catch(它没有任何效果(。只需做:

var stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
s.BranchId,
s.RouteCode,
s.StopName,
s.StopAddress,
s.StopCity,
s.StopState,
s.StopZipPostalCode,
}).First();
//update the counter which will be returned            
itemCountUpdated++;
// etc

共享整个方法之前的背景如下...

一种可能的方法是使用匿名类型,然后在事后重新DistributionStopInformation。像这样:

var anonStop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new { CreatedBy = s.CreatedBy }).First();
var stop = new DistributionStopInformation { CreatedBy = anonStop.CreatedBy };

或者,完全避免匿名类型:

var stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new DistributionStopInformation { CreatedBy = s.CreatedBy }).First();

如果你想使用匿名类型(并且根本不使用DistributionStopInformation(,那么你需要在你的 try catch之外声明一个匿名变量。像这样:

var stop = new { createdby = "a"};
try
{
stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new
{
createdby = s.CreatedBy
}).First();        
}
catch (Exception e)
{
throw;
}

编写Select new { ... }时,您正在创建匿名类型的实例。顾名思义,类型没有名称,因此您无法对它做太多事情,特别是您无法从方法返回它并在调用代码中适当地处理它。此外,您既不能隐式地也不能将它具体转换为所需的类型。

但是,您似乎很清楚查询实际返回的内容,基本上是具有一堆属性的实例。此外,您似乎已经有一个包含这些信息的类:stopInfo(请注意,命名约定建议改用StopInfo(。

所以你应该只使用它:

try
{
stopInfo stop = (from s in rDb.DistributionStopInformations
where s.UniqueIdNo == item.UniqueIdNo
select new stopInfo // here you instantiate your class
{
BranchId = s.BranchId,
RouteCode = s.RouteCode,
StopName = s.StopName,
StopAddress = s.StopAddress,
StopCity = s.StopCity,
StopState = s.StopState,
StopZipPostalCode = s.StopZipPostalCode,
}).First();
}
catch (Exception)
{
// exception-handling, e.g. logging
throw;
}

现在,您甚至可以在 try/catch之外声明变量并将其设置在里面

stopInfo stop;
try { stop = ... }
catch { ... }

最新更新