我正在使用 C# Windows 窗体应用程序使用 Entity Framework (EFWinForms) 使用以下代码从 sql server 数据库表中填充数据:
MyEntityDataModel db = new MyEntityDataModel();
MyEDS = new EntityDataSource();
MyEDS.DbContext = db;
MyDataGridView.DataSource = MyEDS;
MyDataGridView.DataMember = "MyTable";
它工作正常。用户编辑时,添加数据;可以使用以下代码保存数据:
MyEDS.SaveChanges();
我想要一种通过实体数据源过滤这些数据的方法,以便 MyDataGridView 保持可编辑状态,并且用户在过滤后的数据中所做的任何更新仍然可以保存回数据库。 注意:当使用 linq to entity 过滤数据时效果很好,但它只会填充用户无法再次编辑或更新的数据快照。
最佳答案
如果要保留 DataGridView
,在连接模式下使用 Windows 窗体中的 Entity Framework 时,应考虑一些要点。即使应用了过滤器也可编辑。
使用 DbContext 的单个实例
使用您的 DbContext
的单个实例.如果您在保存更改时创建一个新实例,则新实例无法看到您在其他实例上所做的任何更改。所以在表单级别声明它:
TestDBEntities db = new TestDBEntities();
加载数据 - 绑定(bind)到实体的本地存储
当您在连接模式下使用实体时,使用 Load
加载数据db 的方法设置为 db.Products.Load()
或调用 ToList
喜欢db.Products.ToList()
.
绑定(bind)你的 BindingSource
至 db.Products.Local.ToBindingList()
.因此,如果您向绑定(bind)源添加项目或从绑定(bind)源中删除项目,更改跟踪器会检测更改并为您添加和删除项目。
查看 ToBindingList
扩展方法添加 using System.Data.Entity;
.
如果在您的 DataGridView
中启用了添加,然后关闭代理创建以防止过滤时出现异常。
db.Configuration.ProxyCreationEnabled = false;
db.Products.Load();
this.productsBindingSource.DataSource = db.Products.Local.ToBindingList();
使用 Linq 过滤数据
要过滤数据,请使用 linq。你不能使用 Filter
BindingSource
的属性(property)当基础列表为 BindingList<T>
时;只有实现 IBindingListView
的基础列表接口(interface)支持过滤。
要应用过滤,请使用 linq。例如:
var filteredData = db.Products.Local.ToBindingList()
.Where(x => x.Name.Contains(this.FilterTextBox.Text));
this.productsBindingSource.DataSource = filteredData.Count() > 0 ?
filteredData : filteredData.ToArray();
删除过滤器
要删除过滤器,只需再次将绑定(bind)源的数据源设置为实体的本地存储即可。这样添加和删除将在您删除过滤器时起作用。
this.productsBindingSource.DataSource = db.Products.Local.ToBindingList();
添加/删除/编辑
Add 仅在未过滤模式下有效。要让用户添加实体,请删除过滤器。
编辑将在过滤或未过滤模式下进行。
删除在过滤或未过滤模式下均有效。但是如果你使用 BindingNavigator
在过滤模式下,您不能依赖它的删除按钮。要使其适用于过滤模式和非过滤模式,应设置 DeleteItem
BindingNavigator
的属性(property)至 None
并处理它的删除项点击事件并编写自己的代码:
if (productsBindingSource.Current != null)
{
var current = (Product)this.productsBindingSource.Current;
this.productsBindingSource.RemoveCurrent();
if (!string.IsNullOrEmpty(this.FilterTextBox.Text))
db.Products.Local.Remove(current);
}
在处理或关闭您的表单时处理 DbContext
对于现实世界的应用程序,请考虑处理 DbContext
关于处置或关闭表格:
db.Dispose();
示例代码
下面是一个示例代码,其中包含我上面描述的内容。
using System.Data.Entity;
SampleDbEntities db = new SampleDbEntities();
private void Form1_Load(object sender, EventArgs e)
{
db.Configuration.ProxyCreationEnabled = false;
db.Products.Load();
this.productsBindingSource.DataSource = db.Products.Local.ToBindingList();
}
private void FilterButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(this.FilterTextBox.Text))
{
this.productsBindingSource.DataSource = db.Products.Local.ToBindingList();
}
else
{
var filteredData = db.Products.Local.ToBindingList()
.Where(x => x.Name.Contains(this.FilterTextBox.Text));
this.productsBindingSource.DataSource = filteredData.Count() > 0 ?
filteredData : filteredData.ToArray();
}
}
private void productBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
productsBindingSource.EndEdit();
db.SaveChanges();
}
private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
{
if (productsBindingSource.Current != null)
{
var current = (Product)this.productsBindingSource.Current;
this.productsBindingSource.RemoveCurrent();
if (!string.IsNullOrEmpty(this.FilterTextBox.Text))
db.Products.Local.Remove(current);
}
}
关于c# - 如何使用 Entity Framework 以 DataGridView 可编辑和上下文跟踪更改的方式过滤数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35977042/