Dynamic Linq To SQL avec ComboBox et Column.Contains
-
20-08-2019 - |
Question
J'ai une zone de texte, une liste déroulante, un bouton et DataGridView sur un formulaire utilisé pour rechercher et renvoyer les informations client à partir d'une vue MSSQL (vCustomer). Cela fonctionne très bien, mais je sais que mon code peut être plus efficace. Les quatre éléments de la liste déroulante représentent les colonnes à rechercher.
Existe-t-il un moyen simple de convertir les éléments suivants en LINQ to SQL dynamique? Je suis nouveau en C #. J'ai vérifié d'autres articles, mais je n'arrive pas à le faire fonctionner.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
// columns to filter for
string[] list = new string[4];
list[0] = "Name";
list[1] = "CustomerAccountNo";
list[2] = "Telephone";
list[3] = "Postal";
// bind to combobox
cboColumn.DataSource = list;
cboColumn.SelectedIndex = 0;
}
private void btnSearch_Click(object sender, EventArgs e)
{
try
{
Cursor.Current = Cursors.WaitCursor;
CustomerSearchDataContext db = new CustomerSearchDataContext();
IEnumerable<vCustomer> customerQuery = null;
switch (cboColumn.SelectedIndex)
{
case 0:
customerQuery = from c in db.vCustomers
where c.Name.Contains(txtSearch.Text)
orderby c.CustomerAccountNo descending
select c;
break;
case 1:
customerQuery = from c in db.vCustomers
where c.Name.Contains(txtSearch.Text)
orderby c.CustomerAccountNo descending
select c;
break;
case 2:
customerQuery = from c in db.vCustomers
where c.Telephone.Contains(txtSearch.Text)
orderby c.CustomerAccountNo descending
select c;
break;
case 3:
customerQuery = from c in db.vCustomers
where c.Postal.Contains(txtSearch.Text)
orderby c.CustomerAccountNo descending
select c;
break;
}
customerBindingSource.DataSource = customerQuery;
dataGridView1.DataSource = customerBindingSource;
dataGridView1.Columns["CustomerId"].Visible = false;
}
catch (System.Data.SqlClient.SqlException ex)
{
MessageBox.Show("An Error Occured - " + ex.Message,"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
Cursor.Current = Cursors.Default;
}
}
}
La solution
Utilisez [System.Linq.Dynamic][1]
.
Récupérez la condition d'une méthode et utilisez-la dans une requête unique.
switch (choice)
{
case case1:
condition = string.Format("{0}.Contains({1})", "Column", "Value"
break;
Autres conseils
Salut Rony. J'ai essayé votre suggestion et re-factorisé mon code (voir ci-dessous). Toutefois, je reçois une erreur: Aucune propriété ou champ "smith" n'existe dans le type "vCustomer" . Au fait, le MessageBox.Show (condition); La ligne retourne Name.Contains (smith) qui semble correct.
Qu'est-ce que je fais mal? Désolé d'être un noob et merci de votre aide.
Je l'ai compris ... il fallait envelopper la chaîne de recherche avec des guillemets doubles! Le code a été modifié.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
// data column to filter against
string[] list = new string[4];
list[0] = "Name";
list[1] = "CustomerAccountNo";
list[2] = "Telephone";
list[3] = "Postal";
cboColumn.DataSource = list;
cboColumn.SelectedIndex = 0;
// left, right or middle search
string[] list2 = new string[3];
list2[0] = "Contains";
list2[1] = "StartsWith";
list2[2] = "EndsWith";
cboFilterAtt.DataSource = list2;
cboFilterAtt.SelectedIndex = 0;
}
private void btnSearch_Click(object sender, EventArgs e)
{
try
{
Cursor.Current = Cursors.WaitCursor;
CustomerSearchDataContext db = new CustomerSearchDataContext();
//string condition = string.Format("{0}.{1}({2})", cboColumn.SelectedValue, cboFilterAtt.SelectedValue, txtSearch.Text);
string condition = string.Format("{0}.{1}({2})", cboColumn.SelectedValue, cboFilterAtt.SelectedValue, "\"" + txtSearch.Text + "\"");
MessageBox.Show(condition);
var customerQuery = db.vCustomers.Where(condition).OrderBy("CustomerAccountNo");
customerBindingSource.DataSource = customerQuery;
dataGridView1.DataSource = customerBindingSource;
dataGridView1.Columns["CustomerId"].Visible = false;
}
catch (System.Data.SqlClient.SqlException ex)
{
MessageBox.Show("An Error Occured - " + ex.Message,"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
Cursor.Current = Cursors.Default;
}
}
}