UPDATE2 我开始更多地使用James建议使用反射并得到一些工作,它将返回基于字符串变量的属性值。我不想把它作为一个答案,但我觉得它可能不是最好的解决方案。这是代码:
DataContext dataBase = new DataContext();
List<string> listOfFields = new List<string>;
List<string> listOfUsers = new List<string>
//strFields and strNames are strings generated from listOfFields and listOfUsers
IEnumerable<myUserData> userInfo = dataBase.ExecuteQuery<myUserData>
("select " + strFields + " from myUserData where user_id in (" + strNames + ")");
foreach(var user in userInfo)
{
foreach(string field in listOfFields)
{
string fieldValue = user.GetType().GetProperty(field).GetValue(user,null).ToString
Console.WriteLine(fieldValue);
}
}
更新 我正在取得进步!我认为。这可能是一个非常可怕的解决方案和资源匮乏,我还不确定,但它比我一直得到的空白屏幕更好。现在的问题是找到一种方法来返回值而不是字段名称。这是我的代码:
foreach(string userID in listOfUserIDs)
{
//dataBase is a Datacontext
var userInfo = dataBase.myTable
.Where("user_id == @0", userID)
.Select("New(" + strFields + ")");
foreach(var user in userInfo)
{
Console.WriteLine(user);
}
}
无论其他字段如何输出{first_name = JOHN,last_name = DOE}等。我希望我能找到一种方法来修改我的Select子句,只选择值。
我是一名新手程序员,特别是对C#以及任何调用数据库的新手。这是我的第一个使用查询和数据库的项目,我遇到了基于动态查询成功返回结果的问题。
我已经成功创建了一个可以检索正确信息的查询,但我对如何访问检索到的特定字段感到困惑。
IEnumerable<myTable> userInfo = dataBase.ExecuteQuery<myTable>
("select " + Fields + " from myTable where userID in
(" + userNames + ")");
编辑:请原谅我的错误命名约定,但myTable的类型为:System.Collections.Generic.IEnumerable<DatabaseConnection.myTable>{System.Data.Linq.SqlClient.SqlProvider.OneTimeEnumerable<DatabaseConnection.myTable>}
这只是一个占位符名称,在我的数据库中有一个特定的名称。它位于Tables文件夹XD
myTable的类型为DatabaseConnection。 Fields是我正在查找的一串字段,而userNames是一个由逗号分隔的多个用户名的字符串。 示例:Fields =“firstName,lastName,idNumber” userNames =“John,Jane,Bob”
我的问题是,是否有可能在我正在返回的对象类型中为每个用户迭代每个字段?我只是这样明确地看到它:
foreach(var x in userinfo)
{
Console.Writeline(x.firstName);
}
在我目前的情况下,这不起作用,因为用户可能想要与特定用户名相关的其他字段。
我也尝试过使用Dynamic Linq Library,虽然我能够成功设置我的选择字符串,但我不确定当userID等于几个不同的字符串时如何正确设置我的where子句。 (名称的数量并不总是相同)
var dataInfo = dataBase.myTable
.Where("userID == @0", "(" + userIDs + ")")
.Select("New(" + fields + ")");
我已经被困在这几天了。任何帮助将不胜感激。也许我认为解决方案太简单了?我觉得我应该可以在我的第一段代码中使用GetProperties()或类似的东西。
如果这个问题得到解答并且我的格式不佳(我在这里发布第一篇文章),我也很抱歉。在我的研究期间,我无法找到我正在寻找的东西,或者我可能只是没有正确理解代码。再次感谢您的帮助!
编辑:所有这些都是我目前正在处理的Excel Addin。我需要将信息放入List或某种形式的对象中,这样我就可以将每个字段结果放入特定的单元格中。
编辑:如果我使用了错误的术语,请原谅。我觉得我的错误可能在我的Enumerable类型中并命名为“myTable”可能会令人困惑。它是从项目中的.dbml文件中的服务器资源管理器中提取的表。
编辑:对每个用户运行查询并检索该用户名的每个请求字段,效率是多么低效/耗时?如果这只是我需要添加一个简单的循环,我会觉得很傻。
答案 0 :(得分:1)
如果我正确地理解了你的问题并且想要迭代对象的所有属性(不知道它们在编译时是什么),你可以使用Reflection,例如。
foreach (var prop in userInfo.GetType().GetProperties())
{
Console.WriteLine("Property name: " + prop.Name);
Console.WriteLine("Property value: " + prop.GetValue(userInfo, null));
}
答案 1 :(得分:1)
因为看起来你只是使用LINQ to SQL,所以只需使用LINQ来查询数据。我将假设您已经创建了一个DataContext模型,并且MyTable
是模型中的元素包含某种用户信息。
using (MyDataContext db = new MyDataContext()) {
var results = (from m in db.MyTable
where m.UserId == userId
select m);
// Loop over all of the rows returned by the previous query and do something with it
foreach (var m in results) {
// m represents a single row in the results, do something with it.
Console.WriteLine(m.UserId);
}
}
或者,如果您希望查询仅返回一行,那么您只需使用Single
或SingleOrDefault
将结果投影到单个对象中,而不是结果集合:
using (MyDataContext db = new MyDataContext()) {
var singleResult = (from m in db.MyTable
where m.UserId == userId
select m).SingleOrDefault();
// Do something with the single result
if (singleResult != null) {
Console.WriteLine(singleResult.UserId);
}
}
修改强>
前面的示例处理了有关如何使用LINQ查询兼容数据源的基础知识。大多数LINQ提供程序(例如您使用的LINQ to SQL)都支持IQueryable
接口。简短的解释是,此接口允许您动态构建查询,并将该查询的实际执行推迟到您实际尝试访问结果时的最后一分钟。 LINQ查询返回的对象(例如第一个示例中的变量results
)返回IQueryable,其中T是您查询的对象类型。它并不是一个与你想象的List<T>
相同的集合,其中元素已经存在或被明确添加或删除。在第一个示例中,results
实际上没有任何元素,直到foreach
循环尝试迭代结果。
要处理您的过滤方案,让我们继续构建results
查询,直到它满足您的需求,然后我们会在它完好并准备就绪时执行它。
首先假设您的表单有三个要过滤的字段:名字,姓氏和用户ID。为了简单起见,这些字段只是TextBoxes
,如果相应的TextBox
中有任何输入,我们知道要按字段进行过滤。我们还假设不需要验证,用户将始终将正确的数据输入过滤器。
using (MyDataContext db = new MyDataContext()) {
// Build out your base query, which would return everything from MyTable
var results = (from m in db.MyTable
select m);
// Check each textbox for a value to filter by. Add the filter to the base
// query where necessary.
if(!string.IsNullOrEmpty(txtUserId.Text)) {
results = results.Where(x => x.UserId == (int) txtUserId.Text);
}
if(!string.IsNullOrEmpty(txtFirstName.Text)) {
results = results.Where(x => x.FirstName == txtFirstName.Text);
}
if(!string.IsNullOrEmpty(txtLastName.Text)) {
results = results.Where(x => x.LastName == txtLastName.Text);
}
// Loop over all of the rows returned by the previous query and do something with it.
// THIS is the actual point that the SQL would be generated from the query you've
// built and executed against the DB. The elements returned by `results`
// should only meet all of the filters that you the user entered for one or
// more of the fields. Not entering any data would have resulted in all rows being
// returned
foreach (var m in results) {
// m represents a single row in the results, do something with it.
Console.WriteLine(m.UserId);
}
}
上面的示例非常简单,但它代表了您希望将一定数量的字段和AND放在一起的典型过滤方案。我确信有更优雅的方法来封装构建查询过滤器,但核心概念仍然是相同的。只需使用IQueryable<T>
界面并将过滤器表达式链接到它。
这样做只允许您使用AND将谓词链接在一起,并且您不能执行类似“用户ID为6或名称为'John'”的操作。您可以使用System.Linq.Expressions
命名空间构建更复杂的表达式来构建LINQ表达式,但这些表达式相对复杂,在大多数情况下都不是必需的。
答案 2 :(得分:0)
虽然我还没有尝试过DataContext(或.NET 4.5),但在4.0中你可以使用动态类直接访问字段:
IEnumerable<dynamic> userInfo = (from user in users
where user.id equals userId
select new { user.name, user.id /*, ...*/ }).ToList();
foreach (dynamic user in userInfo)
{
Console.WriteLine(user.name);
Console.WriteLine(user.id);
//...
}
dynamic表示在运行时解析的类,因此即使在编码时,您看不到显示字段的智能感知,只要它们是正确的,它就会起作用。
答案 3 :(得分:0)
更新后2:
您可以将嵌套的foreach简化为某些linq。类似的东西:
PropertyInfo[] props = typeof(MyUserData).GetProperties();
var results = from info in userInfo
from p in props
where listOfFields.Contains(p.Name)
select new
{
FieldName= p.Name,
UserId= info.UserId,
FieldValue= p.GetValue(info, null)
};
foreach (var item in results)
{
Console.WriteLine("(userId = {0}) {1} = {2}", item.UserId, item.FieldName, item.FieldValue);
}