filling combo box using LINQ query (distinct) - c#

I have a combocox the name is "cmbModel" I want to fill the database with two different values in a table.
This is what I have done:
private void Form1_Load(object sender, EventArgs e)
{
using (LINQSQLDataContext db = new LINQSQLDataContext())
{
cmbModel.DisplayMember = "szModel";
cmbModel.DataSource = db.VehEcus.ToList<VehEcu>();
}
}
this will fill my cmbModel with szModel column of my table but I want to avoid repeating , how can I use "distinct" in query to achieve my goal?
and also I want to show 2 items of my table like "modelID-szModel" in my combobox
Thanks

If you just want to show a single column anyway you could select that column and use Distinct:
cmbModel.DataSource = db.InfoProg_VehEcus.Select(x => x.szModel).Distinct();

You can apply Distinct() at any point after your query. I recommend doing it before you enumerate.
To create the custom modelID-szModel field, you can enumerate the query using AsEnumerable(), then create an anonymous type and use String.Format to concatenate your values into your new field.
using (LINQSQLDataContext c = new LINQSQLDataContext ())
{
var items = c.VehEcus.Select(t => new
{
a = t.szModel,
b = t.modelID
}).Distinct()
.AsEnumerable().Select(t => new
{
displayMember = String.Format("{0}-{1}", t.a, t.b)
});
cmbModel.DisplayMember = "displayMember";
cmbModel.DataSource = items.ToList();
}

Related

The result of a query cannot be enumerated more than once.

I have a listview dialog to bind a data to that listview.
private void BindListView(string DCLookupMstr_Value, int reportCatId, string DCLookup_Value = null)
{
using (Model.OperationalAnalyticsEntities oadb = new Model.OperationalAnalyticsEntities())
{
var res = oadb.prGetDailyCensusLookup(DCLookupMstr_Value, reportCatId, DCLookup_Value);
Session["LookupValues"] = res;
lvLookup.DataSource = res.ToList();
lvLookup.DataBind();
}
}
And I put a search box(textbox) on that listview dialog. If user type any text/chars, using linq query..populate the listview again with the values which contains given chars. My code is below
protected void txtSearch_TextChanged(object sender, EventArgs e)
{
var text = txtSearch.Text;
//var list = new List<Model.prGetDailyCensusLookup_Result>();
var lookUpValue = Session["LookupValues"] as ObjectResult<Model.prGetDailyCensusLookup_Result>;
var list = lookUpValue.Where(x => x.DCLookup_Value.Contains(text));
lvLookup.DataSource = list.ToList();
lvLookup.DataBind();
}
I am getting the "result of a query cannot be enumerated more than once" where ever i added .ToList(). I am not sure what did I miss.
Please Help!
In BindListView, when you do .ToList(), it enumerates the query for the first time. And what you store in the session is the query itself. When you do .ToList() again in txtSearch_TextChanged, it enumerates the query a second time, which is not supported.
You should store the result of .ToList() in the session, rather than the query:
Session["LookupValues"] = lvLookup.DataSource = res.ToList();
You value you are storing in Session is the LINQ query, not the result of the query. The second time it is used (the list.ToList()) it throws this error.
This is easily fixed by storing the result as a list in Session instead.
var res = oadb.prGetDailyCensusLookup(DCLookupMstr_Value, reportCatId, DCLookup_Value)
.ToList();
Session["LookupValues"] = res;
lvLookup.DataSource = res;
lvLookup.DataBind();

How to get the key(id) of the binded checkListBox

I am have a Windows Forms application and also using SQL to get the data from my db. I have a binded checkListBox in my Windows Forms application and I would like to get the primary key (the value) of all the checked Items in my checkListBox. What I realize is in combo box, they have a build in method 'selectedValue' I am wondering if we can do the same thing in checkListBox by looping through the checkedItems in checkListBox and get its value
Let say in my db table, I have:
EmployeeId Employee Name
1 Jimmy
2 Pam
3 Bob
4 Kobe
My binded checkListBox showed something like
[x]Jimmy
[x]Pam
[]Bob
[]Kobe
Can I get the checkedItem item's id by using sql query. Now let say Jimmy and Pam is checked and I want to get their employeeId. I am not sure how to do it. Help will be appreciated.
select * from employee_table where employeeId = '"+checkListBox.SelectedValue+"'
or
foreach(var item = item.CheckedItems{
select * from employee_table where employeeId = '"items"';
}
You don't need to go to database again to retrieve Id of your items.
You can create a class for items that contains an Id and a Name property and override ToString method to return the string that you want to show in CheckedListBox:
public class ItemModel
{
public int Id { get; set; }
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
Then when loading data, you can select the output and shape it to ItemModel and then add these ItemModels to CheckedListBox:
private void Form_Load(object sender, EventArgs e)
{
var db = new TestDBEntities();
//Select items that you need and shape it to ItemModel
var list = db.Categories.Select(x => new ItemModel
{
Id = x.Id,
Name = x.Name
})
.ToList();
//We cast the list to object[] because AddRange method accept object[]
this.checkedListBox1.Items.AddRange(list.Cast<object>().ToArray());
}
Then when you need to know Id of checked items, you can simply cast each checked item to ItemModel an use its Id property:
private void button1_Click(object sender, EventArgs e)
{
this.checkedListBox1.CheckedItems.Cast<ItemModel>()
.ToList()
.ForEach(item =>
{
MessageBox.Show(string.Format("Id:{0}, Name:{1}", item.Id, item.Name));
});
}
Note:
If you use another method to connect to database, you can simply change this code to satisfy your requirements, for example this code uses ADO.Net objects to shape data to ItemModel:
private void CheckedListBoxSample_Load(object sender, EventArgs e)
{
var connection = #"data source=(localdb)\v11.0;initial catalog=TestDB;integrated security=True;MultipleActiveResultSets=True;";
var command = "SELECT Id, Name From Categories";
var dataAdapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
var table = new DataTable();
dataAdapter.Fill(table);
var list = table.Rows.Cast<DataRow>()
.Select(row => new ItemModel
{
Id = row.Field<int>("Id"),
Name = row.Field<string>("Name")
})
.ToList();
this.checkedListBox1.Items.AddRange(list.Cast<object>().ToArray());
}
Something along these lines might help you.
Basically what it does, is that it builds a parameterized query, and then adds all the selected items using SqlParameters. Then using the reader, you are able to parse each returned record. The code below will probably need some modifications for you to use it, but should help you getting started.
Although I would strongly suggest using an ORM like Entity Framework. Using an ORM you don't have to build your own queries, and allows you to use strong typed classes to "talk" to your database.
var query = "SELECT * FROM employee_table WHERE imployeeId IN (#ids)";
var ids = String.Join(","
MyCheckBoxList.Items
.Cast<ListItem>()
.Where(x => x.Selected)
.Select(x => x.Value);
using (var connection = new SqlConnection(myConnectionString))
{
connection.Open();
using(var command = new SqlCommand(query, connection)
{
command.Parameters.Add("ids", ids);
var reader = command.ExecuteReader();
while(reader.Read())
{
//get all the needed data from the reader
}
}
}

New column is added automaticlly when filling datagridview

I'm using linq to filling my datagrid view with this method:
public List<HopDongCungCap> XemHopDong()
{
return QL.HopDongCungCaps.ToList();
}
and this is my
Result
My dbo.HopDongCungCap just has 1-4 column
but i dont know why it appears the 5th column
Note that dbo.NhaCungCap has a relationship with dbo.HopDongCungCap
Thank you for watching my question!
A solution would be to project the wanted results with Linq like this:
var result = QL.HopDongCungCaps.Select(x => new
{
MaHD = x.MaHD,
TenHD = x.TenHD,
ThoiHan = x.ThoiHan,
NCC = x.NCC
}).ToList();
Note that I leave 'NhaCungCap' out from the result.
This will create a anonymous type.
But you can create a classobject or DTO(Dummy Transfer Object) and project the result that object. and assign that to the datagridview. (.Select(x=> new YourClassDTO...)

Read row values with entities

I am creating a Pie Chart and its name-value pair are being retrieved from the database.
how to read the row details in order to get the values and store it one property ?
public override void OnApplyTemplate()
{
Ram.DataContext = new List<UsageRAM>()
{ new UsageRAM() { name = "Available" , value =/*how to get the value here*/ },
new UsageRAM() { name = "Used" , value =/*how to get the value here*/ }};
base.OnApplyTemplate();
}
public class UsageRAM
{
public string name { get; set; }
public double value { get; set; }
}
EDIT
--Answer which worked for me--
using (DB db = new DB())
{
var row = (from c in db.UsageRAMs
orderby c.UsageRamID descending
select c).First();
Ram.DataContext = new List<UsageRAM>()
{ new UsageRAM() { name = "Available" , value = row.Available},
new UsageRAM() { name = "Used" , value = row.Used }};
If you're using EF, simply add a new model to your project and include the requried table(s) in this model. Then you can use the newly created Entities object to read your db values as follows:
var Rows = context.YourTableName.Where(YourCondition).ToArray();
You can then iterate over the Rows collection using foreach or something.
If you need to read values from a single row, you may want to use First instead of Where above. That will return a single object whose properties will map to your db fields and can directly be assigned in the example code you posted in the question.
EXAMPLE
Say your model's Entity class is named MyEntities and it contains the table UsageRam, which has two fields Available and Used. Then it will take the following code:
using(MyEntities e = new MyEntities)
{
var Row = e.MyTable.First(x => x.UsageRamID = **[ID]**);
MessageBox.Show("Available=" + Row.Available.ToString() + ",Used=" + Row.Used.ToString();
}
I have just shown values in message box, you can assign them to anything you want.
Another Example
using(MyEntities e = new MyEntities)
{
var Rows = e.MyTable.Where(x => x.UsageRamID > 10 && x.UsageRamID < 20);
foreach(var Row in Rows)
MessageBox.Show("Available=" + Row.Available.ToString() + ",Used=" + Row.Used.ToString();
}
EXAMPLE 3
The code in your updated post appears fine to me, though I do have some doubts about the db design, but given your table is indexed on RamUsageID column, this should give you correct results without much performance impact. I generally prefer lambada expressions over query, so I'd rather write it like:
db.RamUsage.OrderByDescending(x => x.RamUsageID).First()

How to imporove the performance of my method created to remove duplicates from a DataView?

I have created a method to remove duplicates froma a DataView. I have not option to change the SQl query , so my only option is to modify the existing data retrieved from the Database in the DataView.
DataView data
Id, Name, Date
1, Paul, 12-05-2011
2, Mark, 12-05-2011
1, Paul, 12-05-2011
2, Mark, 12-05-2011
My method is:
private static void RemoveDuplicates(DataView source, string keyColumn)
{
DataRow[] dataRows = new DataRow[source.Table.Rows.Count];
source.Table.Rows.CopyTo(dataRows, 0);
var uniquePrimaryKeys = new List<Guid>(duplicateTable.Rows.Count);
foreach (DataRow row in duplicateTable.Rows)
{
if (uniquePrimaryKeys.Contains((Guid)row[keyColumn]))
source.Table.Rows.Remove(row);
else
uniquePrimaryKeys.Add((Guid)row[keyColumn]);
}
}
I wonder if there is a better method to achieve the same result but faster.
Actually, ADO.NET added a(n apparently not well known) feature that allows you to create a new table containing the distinct entries from an existing table. Here's how it works:
.....
.....
http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/ed9c6a6a-a93e-4bf5-a892-d8471b84aa3b/
Could you use a linq group as an alternative? I couldn't say how much quicker it would be but I dare say it will be well optimised.
var result = from x in source.Table.AsEnumerable()
group x by new { id = x.Field<int>("ID"), Name = x.Field<string>("Name"), Date = x.Field<DateTime>("Date") }
into groupedResults
select groupedResults.Key;

Categories