linq 反射 WInForms
我对 linq 非常陌生,正在尝试弄清楚如何完成以下任务:
目前,我有一个 Winforms 项目,该项目有一个基本表单,其中 DataRow 作为其成员之一。我有几个派生表单根据 DataTable(SQL 查询结果)中的数据填充 DataRow。派生表单上也有一些控件,这些控件也填充了数据中的值。单击派生表单上的“保存”按钮时,将更新基本表单中的 DataRow,然后派生表单通过 DataAdapter 更新数据库。
我想使用 linqs 替换所有 SQL 命令,因此我尝试通过以下方式使用 LINQ 实现此功能:
我在派生表单中创建了 Linq 查询,并将结果分配给基本表单中的对象。我将基本表单中的对象转换为 Linq 查询的类类型,并使用反射来填充派生表单上的所有控件。单击保存按钮时,我更新对象,但无法更新数据库。
我无法解决的问题是对象更新后如何更新数据库。此时,我没有用于 linq 查询的数据上下文。
我在 linq 查询中使用 SQL 函数,因此我必须为这些值创建一个单独的类,因为我收到匿名类型错误。我可能在这里遗漏了一些东西。
任何帮助将不胜感激,因为我真的 linq 代码是多么干净。
编辑(从 Brad 的编辑复制到 Tomas 的答案):
以下是我的代码的 3 个步骤。
第 1 步 - 从数据库中获取单个数据记录
private void GetDatabaseDetailData()
{
_db = new PriorityDataContext();
DetailData = (from db in _db.tblDatabases
where db.DatabaseID == Id
select db).SingleOrDefault();
DeveloperData = (from db in _db.tblDatabases
where db.DatabaseID == Id
select new DeveloperInfo
{
DeveloperName = _db.func_get_employee_name(db.Developer)
}).SingleOrDefault();
}
第 2 步 - 填充对象中存在其名称的所有控件。 DetailData 对象被转换为传递到此方法的特定类型。为了简洁起见,未显示所有代码。
protected virtual void PopulateDetailControlsA(List<Control> controlContainers, string srcDataTableName)
{
Object data = null;
Type type = null;
switch (srcDataTableName)
{
case "tblDatabases" :
type = typeof(tblDatabase);
data = (tblDatabase)DetailData;
break;
}
if (type != null)
{
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var controlContainer in controlContainers)
{
foreach (var propertyInfo in properties)
{
if (!ControlExists(controlContainer, propertyInfo.Name)) continue;
var txtControl = controlContainer.Controls[propertyInfo.Name] as ExtendedTextBox;
if (txtControl != null)
{
try
{
var value = propertyInfo.GetValue(data, null).ToString();
if (propertyInfo.Name == "row_oper_name" || propertyInfo.Name == "row_last_chng_oper_name")
{
txtControl.Text = RowOperatorData.RowOperatorName;
txtControl.ValueMember = propertyInfo.GetValue(data, null).ToString();
}
else
txtControl.Text = value;
}
catch (NullReferenceException)
{
}
continue;...........
第 3 步 - 尝试将更改保存回派生自的数据库中。
private void SaveData()
{
try
{
_db.SubmitChanges();
}
catch (Exception sqlException)
{
}
}
我真正不清楚的是如何将结果集存储在基本表单中,以便我可以对许多不同的查询使用相同的代码。 DataRow 工作得很好,因为我使用了超过 25 个派生表单的一些代码。
I am very new to linq and am trying to figure out how to accomplish the following:
Currently, I have a Winforms project that has a Base Form with a DataRow as one of it's members. I have several derived Forms populate the DataRow based on data from a DataTable (SQL Query Result). There are controls on the derived Forms that are populated with the values from the data as well. When the Save button on the derived Forms is clicked, the DataRow in the Base Form is updated and then the Derived Form updates the Database via a DataAdapter.
I wanted to replace all of the SQL Commands using linqs so I tried implementing this functionality using LINQ by the following:
I created my Linq query in the Derived Form and assigned the result to an Object in the Base Form. I cast the Object in the Base Form to the class type of the Linq query and use reflection to populate all the controls on the Derived Form. When the save button is clicked I update the Object but I am not able to update the Database.
The problem that I can't solve is how to update the database once the object is updated. At this point I don't have the Data Context that I used for the linq query.
I am using an SQL function within the linq query so I had to create a separate class for these values as I was getting an anonymous type error. I am probably missing something here.
Any help would be most appreciated as I really how clean the linq code is.
Edit (Copied from Brad's Edit to Tomas's answer):
Here are the 3 steps of my code.
Step 1 - Get a singe record of data from database
private void GetDatabaseDetailData()
{
_db = new PriorityDataContext();
DetailData = (from db in _db.tblDatabases
where db.DatabaseID == Id
select db).SingleOrDefault();
DeveloperData = (from db in _db.tblDatabases
where db.DatabaseID == Id
select new DeveloperInfo
{
DeveloperName = _db.func_get_employee_name(db.Developer)
}).SingleOrDefault();
}
Step 2 - Populate all controls whos name exists in the Object. The DetailData Object is cast to the specific type passed into this method. All code not shown for brevity.
protected virtual void PopulateDetailControlsA(List<Control> controlContainers, string srcDataTableName)
{
Object data = null;
Type type = null;
switch (srcDataTableName)
{
case "tblDatabases" :
type = typeof(tblDatabase);
data = (tblDatabase)DetailData;
break;
}
if (type != null)
{
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var controlContainer in controlContainers)
{
foreach (var propertyInfo in properties)
{
if (!ControlExists(controlContainer, propertyInfo.Name)) continue;
var txtControl = controlContainer.Controls[propertyInfo.Name] as ExtendedTextBox;
if (txtControl != null)
{
try
{
var value = propertyInfo.GetValue(data, null).ToString();
if (propertyInfo.Name == "row_oper_name" || propertyInfo.Name == "row_last_chng_oper_name")
{
txtControl.Text = RowOperatorData.RowOperatorName;
txtControl.ValueMember = propertyInfo.GetValue(data, null).ToString();
}
else
txtControl.Text = value;
}
catch (NullReferenceException)
{
}
continue;...........
Step 3 - Try and save changes back to database in the derived From.
private void SaveData()
{
try
{
_db.SubmitChanges();
}
catch (Exception sqlException)
{
}
}
What I am really unclear about hear is how to store the result set in the Base Form so that I can use the same code for many different queries. The DataRow worked great because I use the some code for over 25 derive Forms.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果我理解正确的话,您可以以派生形式创建 DataContext,然后使用它来编写一些查询(以派生形式)。为了能够更新数据库,您的查询必须返回从表中获取的实体(即
select
子句应该只返回实体)。例如:如果您随后修改实体,则可以使用 db.SubmitChanges() 将更改(对实体对象所做的更改)存储到数据库中。为此,您需要原始
db
值。在您的场景中,您需要将
DataContext
(作为字段)存储在派生表单中。如果您需要从基本表单执行更新,那么我建议您定义一个虚拟方法:If I understand you correctly, you create the
DataContext
in a derived form and then use it to write some queries (in a derived form). In order to be able to update the database, your queries must return the entities obtained from the table (i.e. theselect
clause should just return the entity). For example:If you then modify the entities, you can use
db.SubmitChanges()
to store the changes (made to the entity objects) to the database. For this, you need the originaldb
value.In your scenario, you'll need to store the
DataContext
(as a field) in the derived form. If you need to perform the update from the base form, then I suggest you define a virtual method: