Dropdown showing Duplicate Values - c#

I have 4 Dropdown and i am using one Database table for binding Dropdown. But in Dropdown i am getting duplicate values. I used Distinct in select statement but i amnot gettng unique value because it has 4 column.
So is there any way to get unique values or anyway to not getting duplicate value.

If
there are 4 columns
you applied DISTINCT
how did you manage to get duplicates? What duplicates? DISTINCT removes them, so there shouldn't be any rows where those 4 values match.
A blind guess: if you want to get distinct values for one of those columns and don't care about the rest of them, then something like this might help:
select
id, --> this is that "unique" value you're looking for
max(name), --> use one of aggregates for the rest of columns, ...
max(address), --> ... such as MAX in my example
max(phone)
from your_table
group by id --> as aggregates require GROUP BY, you don't need DISTINCT
If it still doesn't help, I'm afraid you'll have to explain the problem better. Don't forget to provide test case.

Distinct() needs to know how to tell if an item in your collection matches another item.
Try something like this.
items.Distinct((itemA, itemB) => string.Equals(
itemA.Name, itemB.Name, StringComparison.InvariantCultureIgnoreCase())

Check your Binding. You should bind only
if(!IsPostBack)
{
//Put the logic for the Dropdown DataBind here
}
If you don't do this you get a new set of Dropdown values with each postback and that's how you got the duplicate values.
If it is not the Binding could you post your SQL statement?

Related

Duplicate Values in DropDown C#

In a dropdown I've got a list of country of this type:
Text: "Italy" Value :"IT"
I need a copy of one of the country in the top of the list referred to the current language of the portal I'm working in, so the user can both select the first or the one into the list. Is just a hint we can say.
So I've just added a copy in this way:
cmbNazione.Items.Insert(0, cmbNazione.Items.FindByText(valori.Rows[0]["M_SOAAuthorityCountry"].ToString().ToUpper()));}
This code works fine. I got my duplicate value and I can select it without problem.
I am stuck when I already have a country that I have to set into the dropDown.
I just wrote that:
cmbNazione.Items.Insert(0, cmbNazione.Items.FindByText(valori.Rows[0]["M_SOAAuthorityCountry"].ToString().ToUpper()));
cmbNazione.ClearSelection();
cmbNazione.Items.FindByText(valori.Rows[0]["M_SOAAuthorityCountry"].ToString().ToUpper()).Selected = true;
The problem is that I receive the error: Cannot have multiple items selected in a DropDownList.
In fact if I check I got both the list Items (first, and the identical in the list) with the prop : selected = true. If I try to make one false both change to false. I cannot use them separately.
I can't understand why I can use them correctly when I select manually, as a user, but not when I try to select them through code.
I also tried something like :
cmbNazione.SelectedIndex = cmbNazione.Items.IndexOf(cmbNazione.Items.FindByText(valori.Rows[0]["M_SOAAuthorityCountry"].ToString().ToUpper()));
But nothing. I'll every time have multiple items in the list of the selected
You should not have a duplicate value as it will confuse the user (if the value is on 2-3 position already) and architecture as retrieval may lead to 2 values being selected.
Your use case seem like you are offering the most commonly used value as the first one and then the remaining. If this is the case, follow the approach outlined below.
Find the ListItem required, then remove it from the list and add on the 1st position. Then mark it as selected.
var preferredItem = cmbNazione.Items.FindByText(...);
if (preferredItem != null) {
cmbNazione.Items.Remove(preferredItem);
cmbNazione.Items.Insert(0, preferredItem);
cmbNazione.SelectedItemIndex = 0;
}
This way, there will be single item being selected and preserve the sanctity of the item (underlying value etc) while still allowing user to have the preferred one on top of list. You can chose to have this as 'pre-selected' or let user select it explictly.

How to add items with value in combobox without any 'auto ordering' of item based on Value?

I am Working in C# winform to load values for a combobox from a datatable with some filter query. Following is the code sample,
repeatCombobox.Items.AddRange(dataTable.Select(myFilterStrin));
repeatCombobox.DisplayMember = "EnumerationText";
repeatCombobox.ValueMember = "Value";
But the problem here is, records selected from the table are 'ordered by value in ascending manner' by default in the combobox.
I would like to load items as it is in the table (no order) rather than any ordering of value either ascending or desending..... but could not do it till now. Can anybody help me out on this?
try
repeatCombobox.Sorted = false;
Edit: if problem is not caused by the combobox's Sorted property, it's probably caused by the missing (or non-incremental) primary key in your database table. DataTable.Select sorts by the primary key by default. If you are not able to add/change the primary key, then you may try adding a new column which has incremental values (maybe you can create a view as well) and use a second parameter in select like dataTable.Select(myFilterStrin, "SortIndex Asc");

Comparing two datasources in C#

I have a gridview, bound to a datasource whose database table contains a foreign key that is associated with the database table that is used as the datasource for a dropdownlist.
What I want to do is if a certain foreignKeyId exists in gridview.datasource, to remove it from dropdownlist.datasource.
To give a clearer idea of what/why I want what I want, the user is able to add entries to the gridview (and therefore the datasource), but I don't want the user to be able to make more than one entry for a specific type. Is there a way that a linq query could do this?
pseudocode (note that I know RemoveObjects() is an invalid method)
var query = DataContext.Items.Where(item => item.TypeId == selectedTypeId);
dropDownList.DataSource.RemoveObjects(query);
Here is how I bind the dropdownlist, so maybe I could do something here to not get the items with already existing TypeId's?
dropDownList.DataSource = DataContext.Items.Select(items => new
{
items.Name,
items.TypeId,
}).ToList();
Any suggestions or answers would be great!
Have you tried using except
dropDownList.DataSource.Except(query)

How to create LookUp fields in DataGridView?

In my DataGridView I'am displaying a buch of columns from one table. In this table I have a column which points to item in another table. As you may already guessed, I want to display in the grid in one column some text value from the second table instead of and ItemID.
I could not find a right example on the net how to do this.
Lets assume that I have two tables in databes:
Table Users:
UserID UserName UserWorkplaceID
1 Martin 1
2 John 1
3 Susannah 2
4 Jack 3
Table Workplaces:
WorkplaceID WorkplaceName
1 "Factory"
2 "Grocery"
3 "Airport"
I have one untyped dataset dsUsers, one binding source bsUsers, and two DataAdapters for filling dataset (daUsers, daWorkplaces).
Code which I am performing:
daUsers.Fill(dsUsers);
daWorkplaces.Fill(dsUsers);
bsUsers.DataSource = dsUsers.Tables[0];
dgvUsers.DataSource = bsUsers;
At this point I see in my dgvUsers three columns, UserID, UserName and UserWorkplaceID. However, instead of UserWorkplaceID and values 1,2,3 I would like to see "Factory", "Grocery" and so on...
So I've added another column to dgvUsers called "WorkplaceName" and in my code I am trying to bind it to the newly created relation:
dsUsers.Relations.Add("UsersWorkplaces", dsUsers.Tables[1].Columns["WorkplaceID"], dsUsers.Tables[0].Columns["UserWorkplaceID"]);
WorkplaceName.DataPropertyName = "UsersWorkplaces.WorkplaceName";
Unfortunately that doesn't work. Relation is created without errors but fields in this column are empty after running the program.
What I am doing wrong?
I would like to also ask about an example with LookUp combobox in DataGridView which allow me to change the UserWorkplaceID but instead of numeric value it will show a tex value which is under WorkplaceName.
Thanks for your time.
In my opinion, the best decision would be to use the DataGridViewComboBoxColumn column type. If you do it, you should create a data adapter with lookup data beforehand and then set DataSource, DataPropertyName, DisplayMember, and ValueMember properties of the DataGridViewComboBoxColumn. You could also set the DisplayStyle property to Nothing to make the column look like a common data column. That's it.
I don't know if you can do exactly what you want, which seems to be binding the DataGridView to two different DataTable instances simulataneously. I don't think the DataGridView class supports that -- or if it does it's a ninja-style move I haven't seen.
Per MSDN, your best bet is probably using the CellFormatting event on the DataGridView and check for when the cell being formatted is in the lookup column, then you could substitute your value from the other table. Use an unbound column for the WorkplaceName column, hide the UserWorkplaceID column and then implement the CellFormatting event handle to look up the value in the row, e.g.:
private void dgv_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e)
{
if (dgv.Columns[e.ColumnIndex].Name.Equals("WorkplaceName")
{
// Use helper method to get the string from lookup table
e.Value = GetWorkplaceNameLookupValue(
dataGridViewScanDetails.Rows[e.RowIndex].Cells["UserWorkplaceID"].Value);
}
}
If you've got a lot of rows visible, this might impact performance but is probably a decent way to get it working.
If this doesn't appeal to you, maybe use the DataTable.Merge() method to merge your lookup table into your main table. A quick glance at one of my ADO.NET books suggests this should work, although I have not tried it. But I'm not sure if this is too close to the idea suggested previously which you shot down.
As for your second question about the lookup combobox, you should really post it in a separate question so it gets proper attention.
You could make SQL do the job instead. Use a join to return a table with Workplace names instead of IDs, output that table into a dataset and use it instead.
eg.
SELECT A.UserID, A.UserName, B.WorkplaceID
FROM Users A
JOIN Workplaces B ON A.UserWorkplaceID = B.WorkplaceID
Then use its output to fill dsUsers.

Best way to save a ordered List to the Database while keeping the ordering

I was wondering if anyone has a good solution to a problem I've encountered numerous times during the last years.
I have a shopping cart and my customer explicitly requests that it's order is significant. So I need to persist the order to the DB.
The obvious way would be to simply insert some OrderField where I would assign the number 0 to N and sort it that way.
But doing so would make reordering harder and I somehow feel that this solution is kinda fragile and will come back at me some day.
(I use C# 3,5 with NHibernate and SQL Server 2005)
Thank you
Ok here is my solution to make programming this easier for anyone that happens along to this thread. the trick is being able to update all the order indexes above or below an insert / deletion in one update.
Using a numeric (integer) column in your table, supported by the SQL queries
CREATE TABLE myitems (Myitem TEXT, id INTEGER PRIMARY KEY, orderindex NUMERIC);
To delete the item at orderindex 6:
DELETE FROM myitems WHERE orderindex=6;
UPDATE myitems SET orderindex = (orderindex - 1) WHERE orderindex > 6;
To swap two items (4 and 7):
UPDATE myitems SET orderindex = 0 WHERE orderindex = 4;
UPDATE myitems SET orderindex = 4 WHERE orderindex = 7;
UPDATE myitems SET orderindex = 7 WHERE orderindex = 0;
i.e. 0 is not used, so use a it as a dummy to avoid having an ambiguous item.
To insert at 3:
UPDATE myitems SET orderindex = (orderindex + 1) WHERE orderindex > 2;
INSERT INTO myitems (Myitem,orderindex) values ("MytxtitemHere",3)
Best solution is a Doubly Linked list. O(1) for all operations except indexing. Nothing can index SQL quickly though except a where clause on the item you want.
0,10,20 types fail. Sequence column ones fail. Float sequence column fails at group moves.
Doubly Linked list is same operations for addition, removal, group deletion, group addition, group move. Single linked list works ok too. Double linked is better with SQL in my opinion though. Single linked list requires you to have the entire list.
FWIW, I think the way you suggest (i.e. committing the order to the database) is not a bad solution to your problem. I also think it's probably the safest/most reliable way.
How about using a linked list implementation? Having one column the will hold the value (order number) of the next item. I think it's by far the easiest to use when doing insertion of orders in between. No need to renumber.
Unfortunately there is no magic bullet for this. You cannot guarentee the order of any SELECT statement WITHOUT an order by clause. You need to add the column and program around it.
I don't know that I'd recommend adding gaps in the order sequence, depending on the size of your lists and the hits on the site, you might gain very little for the over head of handling the logic (you'd still need to cater for the occasion where all the gaps have been used up). I'd take a close look to see what benifits this would give you in your situation.
Sorry I can't offer anything better, Hope this helped.
I wouldn't recommend the A, AA, B, BA, BB approach at all. There's a lot of extra processing involved to determine hierarchy and inserting entries in between is not fun at all.
Just add an OrderField, integer. Don't use gaps, because then you have to either work with a non-standard 'step' on your next middle insert, or you will have to resynchronize your list first, then add a new entry.
Having 0...N is easy to reorder, and if you can use Array methods or List methods outside of SQL to re-order the collection as a whole, then update each entry, or you can figure out where you are inserting into, and +1 or -1 each entry after or before it accordingly.
Once you have a little library written for it, it'll be a piece of cake.
I would just insert an order field. Its the simplest way. If the customer can reorder the fields or you need to insert in the middle then just rewrite the order fields for all items in that batch.
If down the line you find this limiting due to poor performance on inserts and updates then it is possible to use a varchar field rather than an integer. This allows for quite a high level of precision when inserting. eg to insert between items 'A' and 'B' you can insert an item ordered as 'AA'. This is almost certainly overkill for a shopping cart though.
On a level of abstraction above the cart Items let's say CartOrder (that has 1-n with CartItem) you can maintain a field called itemOrder which could be just a comma - separated list of id(PK) of cartItem records relevant . It will be at application layer that you require to parse that and arrange your item models accordingly . The big plus for this approach will be in case of order reshufflings , there might not be changes on individual objects but since order is persisted as an index field inside the order item table rows you will have to issue an update command for each one of the rows updating their index field.
Please let me know your criticisms on this approach, i am curious to know in which ways this might fail.
I solved it pragmatically like this:
The order is defined in the UI.
The backend gets a POST request that contains the IDs and the corresponding Position of every item in the list.
I start a transaction and update the position for every ID.
Done.
So ordering is expensive but reading the ordered list is super cheap.
I would recommend keeping gaps in the order number, so instead of 1,2,3 etc, use 10,20,30... If you need to just insert one more item, you could put it at 15, rather than reordering everything at that point.
Well, I would say the short answer is:
Create a primary key of autoidentity in the cartcontents table, then insert rows in the correct top-down order. Then by selecting from the table with order by the primary key autoidentity column would give you the same list. By doing this you have to delete all items and reinsert then in case of alterations to the cart contents. (But that is still quite a clean way of doing it) If that's not feasible, then go with the order column like suggested by others.
When I use Hibernate, and need to save the order of a #OneToMany, I use a Map and not a List.
#OneToMany(fetch = FetchType.EAGER, mappedBy = "rule", cascade = CascadeType.ALL)
#MapKey(name = "position")
#OrderBy("position")
private Map<Integer, RuleAction> actions = LazyMap.decorate(new LinkedHashMap<>(), FactoryUtils.instantiateFactory(RuleAction.class, new Class[] { Rule.class }, new Object[] { this }));
In this Java example, position is an Integer property of RuleAction so the order is persisted that way. I guess in C# this would look rather similar.

Categories