replacing all matching values in datatable based on another in c# - c#

i have a dataTable like this :
and a second one like this :
how can i replace MIN_QUANTITY,MAX_QUANTITY,DISCOUNT_VALUE from table two by the values in table 1 based on there GEN_CODE
PS:the GEN_CODE in the second table is not unique and can be duplicated and the duplicate rows should also be added in the first table
i tried to use :
Table1.Merge(Table2, false, MissingSchemaAction.Ignore);
but the duplicates rows are not added how should i fix this ?

Assuming you stored every occurrences of table 1 and 2 into a "record" class that has every column of your datatable as a property.
It can be easily done using LINQ.
Let's say that records from table 1 are stored in List<record> List1 and the other records from table 2 in List<records> List2.
foreach (record reference_record in List1)
{
foreach(record record_to_update in List2.Where(x=>x.GEN_CODE == reference_record.GEN_CODE).Select(x=>x).ToList())
{
record_to_update.MIN_QUANTITY = reference_record.MIN_QUANTITY;
record_to_update.MAX_QUANTITY = reference_record.MAX_QUANTITY;
record_to_update.DISCOUNT_VALUE = reference_record.MAX_QUANTITY;
}
}
You'll need to bind your data table on the following class:
public class record
{
public string GEN_CODE { get; set; }
public string PRODUCT_NAME { get; set; }
public string MIN_QUANTITY { get; set; }
public string MAX_QUANTITY { get; set; }
public string DISCOUNT_VALUE { get; set; }
//... add other properties here
}

Related

QueryAsync returning nothing for ID column (auto number column)

I have a Xamarin.Forms App with a SQLite database. I'm experiencing an issue when trying to retrieve values from an auto-incremented column using QueryAsync. The function looks like this:
public async Task<Dictionary<int, string>> GetDicIDsNames()
{
List<IdName> idNamesList = await db.QueryAsync<IdName>("SELECT StudentID, Name FROM [Student]");
Dictionary<int, string> dicIDsNames = new Dictionary<int, string>();
foreach (IdName item in idNamesList)
{
dicIDsNames.Add(item.id, item.name);
}
return dicIDsNames;
}
The goal of the function is to return a Dictionary of Student IDs and Names. When I put a breakpoint in the code I was able to see that the first line of code populates the idNamesList with all the student names, but all of the IDs are 0 and I don't know why.
I have a Student class/table with a definition like this:
public class Student
{
[PrimaryKey, AutoIncrement]
public int StudentID { get; set; }
public string Name { get; set; }
....
}
There are additional fields but I'll leave them out since they are irrelevant to the question.
Here is a short class "IdName" I created for working with the return values:
public class IdName
{
public int id { get; set; }
public string name { get; set; }
}
Another kind of odd thing is that when I query the database and return a full student object the StudentID property is returned/set properly. I could easily return every student in the table then loop through to extract the id and name fields from there but that would be quite inefficient.
Why would it be returning 0 or null values? Or if there is a way I can select the columns by index that would work too since I just need the first 2 columns from the table.
I guess it turns out that my return data type of IdName has to have variables with the exact same names as the column names in my table. I thought the variables could be any name but I tried this out and it solved the issue
public class IdName
{
public int StudentID { get; set; }
public string Name { get; set; }
}
Thanks mjwills for helping me find the solution.

Creating Complex Automapper

I am trying to use the automapper to map my Database table output to my class object. But the table has 3 rows that are all belong to single employee data which needs to be assigned to a single class object. How we can we create mapper ? Is it possible to create mapper with this table data ?
How can I write Autommapper to populate the class EmployeeDetails
public class EmployeeDetails
{
public string EmpNo { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<Phone> Phone { get; set; }
}
public class Address
{
public string Address_1 { get; set; }
public string City { get; set; }
}
public class Phone
{
public string PhoneType { get; set; }
public string PhoneNo { get; set; }
}
Datatype EmpNo Name Address_1 City PhoneType PhoneNo
Name 1234 Test Test addr Testcity Null Null
Phone 1234 Null Null Null Mobile 123456
Phone 1234 Null Null Null Work 789546
public IEnumerable< EmployeeDetails > GetEmployeeDetails()
{
return ExecuteEmpReader< EmployeeDetails>().ToList();
}
private IEnumerable<T> ExecuteEmpReader <T>()
{
DataTable dt=new Datatable();
//Assume the dt will be loaded as per the above table.
foreach (DataRow item in dt.Rows)
{
yield return _mapper.Map<T>(item)
}
}
I don't believe there is a way to do what you want using solely Automapper. Specifically because of the merging of rows into one. This link shows how you can at least unflatten your object to your desired object structure, but then you would need to write the logic to merge the employees addresses and phone numbers yourself.
http://martinburrows.net/blog/2016/01/18/automatic-unflattening-with-automapper
On the contrary to make your resulting code easier to maintain in future. I would recommend creating some views of your Employee Object, one for Employee, one for Address, and one for Phone. Then you can use EF to map your views straight to your objects.

Change the order of asp:GridView *autogenerated* columns

First let me say that I've seen similar questions on StackOverflow, but none that I've seen deal specifically with auto-generated columns.
I have a asp:GridView that I am binding to an IEnumerable<Data>, where Data can vary depending on runtime input. However, each Data class shares a couple base properties:
public class BaseData
{
public int ID { get; set; }
public string Name { get; set; }
}
public class AddressData : BaseData
{
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; };
}
public class ContactData : BaseData
{
public string Phone { get; set; }
public DateTime LastUpdated { get; set; }
// tons more public properties...
}
// More classes with lots of different public properties...
These different classes are populated by a database query, so I want to auto-generate columns when I place the data in the GridView because of the large number of different fields. However, I want to display the columns that are in the shared base class first. If I just assign the IEnumerable<Data> to the GridView datasource, the base classes properties are added last to the GridView's columns. I tried remedying the situation like this:
// Callback after getting data from database
public void SetGridView<Data>(IEnumerable<Data> rows) where Data : BaseData
{
// Make sure these columns show up first
BoundField ID = new BoundField() { HeaderText = "ID", DataField = "ID" };
BoundField Name = new BoundField() { HeaderText = "Name", DataField = "Name" };
myGridView.Columns.Clear();
myGridView.Columns.Add(ID);
myGridView.Columns.Add(Name);
myGridView.AutoGenerateColumns = true;
myGridView.DataSource = rows;
myGridView.DataBind();
}
However, this just duplicates the columns at the beginning and end, so the header looks like this:
ID Name Street1 Street2 City State ZipCode ID Name
So is there a way for me to move the columns that I know will be there (base class) to the beginning of the GridView's columns while still having the convenience of auto-generating all the other columns?
Since you are forced to use auto-generated columns, I'd just create an intermediate DataTable to bind the GridView to. In that DataTable object, you can add your columns in the order you prefer. The GridView should then bind in that same order.
Edit:
Modify BaseData, add the following:
private DataTable dataForDisplay;
// This would be overridden by all child classes, adding their columns in the order you want
public virtual DataTable GetDataForDisplay()
{
dataForDisplay = new DataTable();
dataForDisplay.Columns.Add("ID");
dataForDisplay.Columns.Add("Name");
// If you want to change the order, just don't call the base.GetDataForDisplay()
dataForDisplay.Rows.AddRange(this.ID, this.Name);
return dataForDisplay;
}
Then all of the other child classes will override GetDataForDisplay().

Entity framework raw SQL Query

I have to select multiple columns from a database and I don't have a matching entity.
so my query looks like this:
var result = _dbContext.Database.SqlQuery<List<string>>(
"select ID, NAME, DB_FIELD from eis_hierarchy");
I am getting the result set, each row contains list of strings but count is 0.
So how do I select multiple columns using Database.SqlQuery?
You have to capture the results into a class with matching property names, and (at least) a parameterless constructor:
class DbResult
{
public int ID { get; set; }
public string NAME { get; set; }
public string DB_FIELD { get; set; }
}
var result = _dbContext.Database.SqlQuery<DbResult>(
"select ID, NAME, DB_FIELD from eis_hierarchy");

search for int id starting with x entity framework 4.1

I currently have an Entity Framework model that collects data from a legacy database and I am currently using an int on my Id properties
I am attempting to build a search box with autocomplete capabilities and want to have the autocomplete function to return a subset of records based on whether the sample id either contains or starts with (final design decision not made yet) and I am running into problems with converting the integer id to a string as I would normally use a recs.Id.toString().StartsWith(recordId) but this is apparently not supported by the Entity Framework
Is there a way around this limitation ?
My code looks like the following
Model:
public class Sample
{
public Sample()
{
Tests = new List<Test>();
}
public int Id { get; set; }
public DateTime SampleDate { get; set; }
public string Container { get; set; }
public string Product { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public virtual SamplePoint SamplingPoint { get; set; }
public virtual SampleTemplate SampleTemplate { get; set; }
public Customer ForCustomer { get; set; }
public virtual ICollection<Test> Tests { get; set; }
}
and the query I am currently trying to apply to this model
[HttpGet]
public JsonResult AutoComplete(string partialId)
{
var filteredSamples =
repo.AllSamples.Where( s =>
String.Compare(s.Status, "A", false) == 0
&& (s.Id.ToString()).StartsWith(partialId)
).ToList();
return Json(filteredSamples, JsonRequestBehavior.AllowGet);
}
Any ideas would be awesome I am out of ideas at this point
No matter what you do, this is going to result in some awful performance on large datasets, because you will not be able to use any indices. My recommendation would be to use a trigger or scheduled task to store the leading digit in a separate field and filter on that.
I ended up adding a view for autocomplete data and converting the data to string in the select statement and this solved my issue
Wild thought: how about your create a computed, persisted column on your database table, that converts your ID (INT) into a string?
Then you could:
put an index on that column
use a simple string comparison on that string column
Basically, you need this:
ALTER TABLE dbo.YourTable
ADD IDAsText AS CAST(ID AS VARCHAR(10)) PERSISTED
Now update you EF model - and now you should have a new string field IDAsText in your object class. Try to run your autocomplete comparisons against that string field.

Categories

Resources