如何使用Entity Framework以DataGridView可编辑和上下文跟踪更改的方式过滤数据?
我正在使用C#Windows Form Application使用以下代码使用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过滤数据时,它工作得很好,但它只是填充了用户无法再次编辑或更新的数据快照。
当您希望在连接模式下使用Windows窗体中的entity framework时,您应该考虑一些重要的要点。 然后,您可以正确保存更改。
使用DbContext的单个实例
使用DbContext
的单个实例。 如果在保存更改时创建新实例,则新实例无法看到您在其他实例上所做的任何更改。 所以在表单级别声明它:
TestDBEntities db = new TestDBEntities();
加载数据 – 绑定到实体的本地存储
在连接模式下使用实体时,首先使用db.Products.ToList()
或db.Products.Load()
加载数据,然后将BindingSource
绑定到db.Products.Local.ToBindingList()
。
它将网格直接绑定到实体集。 因此,如果您在绑定源中添加或删除,则更改跟踪器会检测更改并为您添加和删除项目。 您可以这样加载数据:
//using System.Data.Entity; db.Configuration.ProxyCreationEnabled = false; db.Products.Load(); // or db.Products.ToList(); this.productBindingSource.DataSource = db.Products.Local.ToBindingList();
使用Linq过滤数据
要过滤数据,请使用linq。 当基础列表是BindingList
时,您不能使用BindingSource
Filter
属性; 只有实现IBindingListView
接口的基础列表才支持过滤。 例如,您可以通过以下方式过滤数据:
var filteredData = db.Products.Local .Where(x => x.Name.Contains(this.FilterTextBox.Text)); this.productBindingSource.DataSource = filteredData;
删除filter
要删除filter,只需将绑定源的数据源再次设置为实体的本地存储。 这样,当您删除filter时,添加和删除将起作用。
this.productBindingSource.DataSource = db.Products.Local.ToBindingList();
添加/删除/编辑
添加仅适用于未过滤模式。 要让用户添加实体,请删除filter。 你可以使它工作,但它是合理的不要触摸它。
编辑将在过滤或未过滤模式下工作。
删除可以在过滤或未过滤模式下工作。 但是如果你使用BindingNavigator
你不能依赖它的删除按钮,你应该设置它的DeleteItem
no none并处理它的删除项单击事件并编写你自己的代码:
db.Products.Local.Remove((Product)this.productBindingSource.Current); this.productBindingSource.RemoveCurrent();
示例代码:
下面是一个示例代码,其中包含我上面描述的内容。
using System.Data.Entity; //... TestDBEntities db = new TestDBEntities(); private void Form1_Load(object sender, EventArgs e) { db.Configuration.ProxyCreationEnabled = false; db.Products.ToList(); this.productBindingSource.DataSource = db.Products.Local.ToBindingList(); } private void FilterButton_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(this.FilterTextBox.Text)) { this.productBindingSource.DataSource = db.Products.Local.ToBindingList(); } else { var filteredData = db.Products.Local .Where(x => x.Name.Contains(this.FilterTextBox.Text)); this.productBindingSource.DataSource = filteredData; } } private void productBindingNavigatorSaveItem_Click(object sender, EventArgs e) { db.SaveChanges(); } private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e) { db.Products.Local.Remove((Product)this.productBindingSource.Current); this.productBindingSource.RemoveCurrent(); }
虽然我不确定您的可能用途,但我通常在绑定源上使用filter属性来选择某些记录而不放弃更新数据库的能力。 像这样的东西:
// Grab search string from SearchBox string strSearch = Convert.ToString(RichSearchBox.Text); // Apply Filter to BindingSource tblContactsBindingSource.Filter = "FileAs LIKE '*" + strSearch + "*'";
然后使用Binding Source作为数据网格视图的数据源:
// Bind DataGridView to BindingSource recipientGridView.DataSource = tblContactsBindingSource;