如果我没记错的话,当我在using SqlConnection块内使用yield 时,我得到了运行时异常.
using (var connection = new SqlConnection(connectionString))
{
var command = new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
yield reader[0];
}
// Call Close when done reading.
reader.Close();
}
Run Code Online (Sandbox Code Playgroud)
当我用yieldList 替换这些问题时,我每次迭代都添加了项目.
在内部using StreamReader块时,我没有发生同样的问题
using (var streamReader = new StreamReader(fileName))
{
string line;
while ((line = streamReader.ReadLine()) != null)
{
yield return line;
}
}
Run Code Online (Sandbox Code Playgroud)
有没有解释为什么例外事件发生在前一种情况而不是后者?这个建筑是否可取?
编辑为了得到我过去做的错误(早期处理)你应该调用下面的第一个方法:
IEnumerable<string> Read(string fileName)
{
using …Run Code Online (Sandbox Code Playgroud) 我无法理解为什么Program.Fetch1,Program.Fetch2也不会导致完全相同的执行顺序.唯一的区别是Program.Fetch1调用Program.Fetch实际的获取操作.
class Program
{
static IEnumerable<int> Fetch1()
{
using (Context c = new Context())
{
return Fetch(c);
}
}
static IEnumerable<int> Fetch(Context c)
{
foreach (int i in c.Fetch())
{
yield return i;
}
}
static IEnumerable<int> Fetch2()
{
using (Context c = new Context())
{
foreach (int i in c.Fetch())
{
yield return i;
}
}
}
static void Main(string[] args)
{
Console.WriteLine("Fetch1:");
foreach (int i in Fetch1())
{
Console.WriteLine(i);
} …Run Code Online (Sandbox Code Playgroud) 我在这里寻找指针和信息,我会做这个CW,因为我怀疑它没有一个正确答案.这是针对C#的,因此我将在下面对Linq进行一些引用.我也为这篇长篇大论道歉.让我在这里总结一下这个问题,然后是完整的问题.
简介:在UI/BLL/DAL/DB 4层应用程序中,如何更改用户界面,以显示更多列(例如在网格中),避免泄漏通过业务逻辑层进入数据访问层,掌握要显示的数据(假设它已经在数据库中).
让我们假设一个有3(4)层的分层应用程序:
在这种情况下,DAL负责构造SQL语句并对数据库执行它们,返回数据.
"正确"构建这样一个层的唯一方法就是总是"select*"吗?对我来说这是一个很大的禁忌,但让我解释为什么我在想.
让我们说,对于我的用户界面,我希望显示所有拥有活跃就业记录的员工."活跃"是指今天的就业记录包含今天(或者甚至是我可以在用户界面中设定的日期).
在这种情况下,假设我想向所有这些人发送一封电子邮件,因此我在BLL中有一些代码可以确保我还没有向同一个人发送过电子邮件,等等.
对于BLL,它需要最少量的数据.也许它调用数据访问层来获取活动员工列表,然后调用以获取它发送的电子邮件列表.然后它加入这些并构造一个新列表.也许这可以在数据访问层的帮助下完成,这并不重要.
重要的是,对于业务层,它实际上并不需要太多数据.也许它只需要每个员工的唯一标识符,对于两个列表,匹配,然后说"这些是活动的那些的唯一标识符,您还没有发送电子邮件到".然后构建DAL代码,构造只检索业务层需要的SQL语句吗?IE浏览器.只是"SELECT id FROM employees WHERE ..."?
那么我该怎么做用户界面呢?对于用户来说,这或许会是最好的,包括了很多信息,这取决于为什么我要发送电子邮件.例如,我可能想要包括一些基本的联系信息,或者他们工作的部门,或者他们的经理姓名等,而不是说我至少要显示姓名和电子邮件地址信息.
用户界面如何获取数据?我是否更改了DAL以确保将足够的数据返回给UI?我是否更改BLL以确保它为UI返回足够的数据?如果从DAL返回到BLL的对象或数据结构也可以发送到UI,那么BLL可能不需要进行太多的更改,但是UI的要求会影响超出应该与之通信的层. .如果这两个世界在不同的数据结构上运行,则可能必须对两者进行更改.
那么当UI被更改时,为了进一步帮助用户,通过添加更多列,我需要多深才能更改UI?(假设数据已存在于数据库中,因此不需要进行任何更改.)
提出的一个建议是使用Linq-To-SQL和IQueryable,这样如果DAL处理什么(如在什么类型的数据中)和为什么(如WHERE-clauses中)返回IQueryables,那么BLL可以可能会将这些内容返回到UI,然后可以构建一个Linq查询来检索所需的数据.然后,用户界面代码可以拉入所需的列.这将有效,因为使用IQuerables,UI最终会实际执行查询,然后它可以使用"select new {X,Y,Z}"来指定它需要的内容,甚至可以在必要时加入其他表.
这看起来很混乱.UI执行SQL代码本身,即使它已隐藏在Linq前端后面.
但是,为了实现这一点,不应该允许BLL或DAL关闭数据库连接,并且在IoC类型的世界中,DAL服务可能比UI代码所希望的更快地被处理掉,因此Linq查询可能最终会出现"无法访问已处置对象"的异常.
所以我正在寻找指针.我们有多远?你是怎么处理的?我认为UI的更改将通过BLL泄漏到DAL中是一个非常糟糕的解决方案,但是现在它看起来并不像我们能做得更好.
请告诉我我们有多愚蠢并证明我错了?
请注意,这是一个遗留系统.多年来,更改数据库模式的范围还不在范围内,因此使用ORM对象的解决方案基本上与"select*"相当,实际上并不是一种选择.我们有一些大型表格,我们希望避免在整个图层列表中提取.
c# business-logic data-access-layer isolation leaky-abstraction