c# - 如何使用 Entity Framework 以 DataGridView 可编辑和上下文跟踪更改的方式过滤数据?

标签 c# .net winforms entity-framework datagridview

我正在使用 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/

相关文章:

c# - 如何打印出树结构?

c# - 在 .NET 中仅使用没有相应字段的属性的缺点?

.net - 从托管代码调用具有固定缓冲区的非托管 DLL(编码问题)

c# - 替换 XML 文本的最佳方式

c# - 通过 ODBC 执行参数化 SQL 存储过程

C#跨线程调用问题

c# - Nunit3 OneTimeSetUp 和 OneTimeTeardown 不工作

c# - 从另一个页面的文本 block 中抓取文本

c# - 为什么会出现编译错误 "Use of unassigned local variable"?

c# - RemoveAt 收集失败