Como filtrar os dados usando a plataforma de entidade de uma forma que a DataGridView seja editável e as alterações da faixa de contexto?
estou a usar a aplicação C# Windows Form para preencher dados da tabela de bases de dados sql server usando o Entity Framework (EFWinForms) usando o seguinte código:
MyEntityDataModel db = new MyEntityDataModel();
MyEDS = new EntityDataSource();
MyEDS.DbContext = db;
MyDataGridView.DataSource = MyEDS;
MyDataGridView.DataMember = "MyTable";
Funciona bem. Quando o utilizador editar, adicione dados; os dados podem ser gravados usando o seguinte código:
MyEDS.SaveChanges();
quero uma forma de filtrar estes dados através da fonte de dados da entidade para que a MyDataGridView permaneça editável e qualquer actualização feita pelo Utilizador em dados filtrados possa ainda ser gravada de volta à base de dados. Nota: ao usar o linq para entidade para filtrar dados funciona muito bem, mas ele apenas povoar um instantâneo de dados que não pode ser editado ou atualizado pelo Usuário novamente.
2 answers
Existem alguns pontos importantes que você deve considerar quando você quer trabalhar com a estrutura de entidade em formulários windows no modo conectado. Então você pode salvar as alterações corretamente.
Use uma única instância do seu DbContext
Utilize uma única instância do seu DbContext
. Se você criar uma nova instância ao Salvar alterações, a nova instância não pode ver nenhuma alteração que você fez em outra instância. Declara-o ao nível do formulário:
TestDBEntities db = new TestDBEntities();
Carregar Os Dados-Ligar A Armazenamento Local de entidades
Quando você trabalha com entidades em modo conectado, primeira carga de dados usando db.Products.ToList()
ou {[8] } em seguida, ligar o seu BindingSource
a db.Products.Local.ToBindingList()
.
Liga a grade diretamente ao conjunto de entidades. Por isso, se adicionar ou remover do código de ligação, mude o localizador detecta as alterações e adiciona e remove os itens para si. Você pode carregar dados desta forma:
//using System.Data.Entity;
db.Configuration.ProxyCreationEnabled = false;
db.Products.Load(); // or db.Products.ToList();
this.productBindingSource.DataSource = db.Products.Local.ToBindingList();
Filtrar Os Dados Usando O Linq
Para filtrar os dados, use o linq. Não pode utilizar Filter
propriedade de BindingSource
Quando a a lista subjacente é BindingList<T>
; apenas as listas subjacentes que implementam a filtragem de suporte da interface IBindingListView
. Por exemplo, pode filtrar os dados desta forma:
var filteredData = db.Products.Local
.Where(x => x.Name.Contains(this.FilterTextBox.Text));
this.productBindingSource.DataSource = filteredData;
Remover O Filtro
Para remover o filtro, basta definir a fonte de dados da sua fonte de ligação para o armazenamento local das suas entidades novamente. Desta forma, adicionar e remover irá funcionar quando você remover o filtro.
this.productBindingSource.DataSource = db.Products.Local.ToBindingList();
Adicionar/Remover/Editar
A adição só funcionará em modo não filtrado. Para deixar o utilizador adicionar entidades, Remover filtro. podes fazê-lo funcionar, mas é razoável não lhe tocares.
A edição funcionará tanto em modo filtrado como em modo não filtrado.
A remoção pode funcionar tanto no modo filtrado como no modo não filtrado. Mas se você usar BindingNavigator
Você não pode confiar no seu botão Apagar e você deve definir o seu DeleteItem
nenhum e lidar com o seu item apagar carregue em evento e escreva o seu próprio código:
db.Products.Local.Remove((Product)this.productBindingSource.Current);
this.productBindingSource.RemoveCurrent();
Código Da Amostra:
Abaixo está um código de amostra que contém o que eu descrevi acima.
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();
}
Embora não tenha a certeza do seu possível uso, geralmente USO a propriedade do filtro numa fonte de ligação para seleccionar certos registos sem desistir da capacidade de actualizar a base de dados. Algo do género:
// Grab search string from SearchBox
string strSearch = Convert.ToString(RichSearchBox.Text);
// Apply Filter to BindingSource
tblContactsBindingSource.Filter = "FileAs LIKE '*" + strSearch + "*'";
Utilize então a fonte de ligação como a fonte de dados para a área da grelha de dados:
// Bind DataGridView to BindingSource
recipientGridView.DataSource = tblContactsBindingSource;