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()
Related
I have a table called PCRStatusLog with a column called PromoteDate. This column is fed a date where data from an excel sheet was sent from staging to the primary database. It's a new column, hasn't been used yet so for most records it is null, but we need to display the data of this column to our webapp. Most of the logic to do so already exists and the models are ADO.NET entity models generated from EF Designer From Data Base in Visual Studio.
In the table, PromoteDate is DATETIME and nullable (SQL Server) and the model for the table looks like this:
public partial class PCRStatusLog
{
// ... list of fields and properties
public Nullable<System.DateTime> PromoteDate { get; set; }
}
And was generated code, not entered manually. There's nothing special about that class, it's only a list of getters/setters that map to a table, a typical simple entity model.
Here is where it is used (I didn't write most of this code, I only added changes concerning the PromoteDate):
public List<PCRTracking> GetPCRTrackingDetails()
{
//...
List<PCRTracking> pcrDetails = (from bulk in providerMasterContext.BULK_UPLOADS
join ps in providerMasterContext.PROCESSSTATUS on bulk.ProcessStatusID equals ps.ProcessStatusID
join p in providerMasterContext.PLANs on bulk.PlanCode equals p.PlanCode
where bulk.CreateDate > compDateTime
orderby bulk.BulkUploadID descending
select new PCRTracking
{
FileID = bulk.BulkUploadID,
FileName = bulk.BulkUploadActualFileName,
PlanName = p.PlanCode,
FileStatus = string.Empty,
RecordsSubmitted = 0,
RecordsFailed = 0,
ValidationStatusReports = string.Empty,
ErrorMessage = string.Empty,
Submitter = bulk.SubmissionByID,
SubmitterName = bulk.SubmissionByName,
SubmitDate = (DateTime)bulk.SubmissionDateTime
}).ToList<PCRTracking>();
foreach (PCRTracking item in pcrDetails)
{
var promoteDateQuery = (from psl in providerMasterContext.PCRStatusLogs
where psl.BulkUploadID == item.FileID
select psl).FirstOrDefault();
item.PromoteDate = promoteDateQuery.PromoteDate;
//... rest of the code doesn't make use of PromoteDate
All of the other fields in PCRTracking object work fine, but PromoteDate keeps coming up as null, even on the one record that I manually edited to have a date.
Even here, where I examine the object returned by querying the one record I know has a date under promote date, it turns out null:
// from the Main method of a test console project
var providerMasterContext = new BulkPCRDAL().providerMasterContext;
var query =(from psl in providerMasterContext.PCRStatusLogs
where psl.BulkUploadID == 43
select psl).FirstOrDefault();
foreach(var prop in query.GetType().GetProperties())
{
Console.WriteLine(prop.GetValue(query));
}
Console.ReadLine();
It grabs all the properties on the object, and everything looks right, and matches whats in the database, except this one PromoteDate property.
Am I missing something?
Note that everything else in this model works, all other fields display data from the db, this one field is the only one that won't work.
I am not sure on linq for thisHow to get record from other table based on a value from first table with linq expression.
public IQueryable GetAllMeeting()
{
var allMeeting = from xx in _dbContext.tbl_Meeting
select new Meeting
{
Meeting_Attendee_Id = xx.Attendees,
Meeting_Agenda = xx.Agenda,
Meeting_Date = xx.Date,
Id = xx.Id,
Meeting_Subject = xx.Subject,
CreatedById = xx.Created_By
};
var meetingCreatedBy = _dbContext.tbl_User.SingleOrDefault(x=>x.Id == allMeeting.Creaated)
return allMeeting; // not sure if same thing can be done while fatching allMeetings or need to do a separate?
}
You can use let clause See Microsoft Docs
public IQueryable GetAllMeeting()
{
var allMeeting = from xx in _dbContext.tbl_Meeting
let meetingCreatedBy = _dbContext.tbl_User.FirstOrDefault(x=>x.Id == xx.CreatedById)
select new Meeting
{
Meeting_Attendee_Id = xx.Attendees,
Meeting_Agenda = xx.Agenda,
Meeting_Date = xx.Date,
Id = xx.Id,
Meeting_Subject = xx.Subject,
CreatedById = xx.Created_By,
CreatedBy = meetingCreatedBy !=null ? meetingCreatedBy.Name : "" //Or whatever property/column you have for displaying the name
};
return allMeeting;
}
Note: If these two tables are related with each other and the relationships are properly defined i.e. Created_By of table tbl_Meeting is connected with Id of tbl_User .You can simply use the navigation property to retrieve the user who created the meeting (i.e. xx.tbl_User.Name) . I would strongly recommend reading navigation properties and relationships
You need to perform join operation (probably left join) between two entities. Also add the required property inside model objec and return the value.
I am looking for a way to obtain my property names in a SSIS data flow task Script Component. I have been searching high and low only finding this. I have been trying to get this code to work, but I am too novice to understand what is happening here and I don't feel it is explained very well(no offense).
The source before this component is using a SQL query joining two tables. Inside the component, I would like to compare column to column. Then call an update method I created to use SqlConnection to perform the update.
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
if (Row.TableALastName != Row.TableBLastName)
// Call the update method if the last name did not match.
this.UpdateRecord("TableBLastName", Row.TableALastName.ToString(), Row.TableAAssociateId.ToString());
}
}
private void UpdateRecord(string columnName, string change, string associateId)
{
SqlConnection sqlConnection;
sqlConnection = new SqlConnection(this.Variables.Connection);
string updateQuery = "UPDATE [SomeDataBase].[dbo].[TableB] SET " + columnName + " = " + change + " WHERE [Associate_ID] = " + associateId;
using (SqlCommand cmd2 = new SqlCommand(updateQuery, sqlConnection))
{
sqlConnection.Open();
cmd2.ExecuteNonQuery();
sqlConnection.Close();
}
}
I would like to somehow get the PropertyName of Row.TableBLastName instead of having to hard code "TableBLastName" for each test I am doing, which will be a lot.
The problem is that the input buffer class does not have Property.GetName() This also means I can't add a method to the class to get the property names, as it is regenerated each run.
public Input0_ProcessInputRow(Input0Buffer Row)
{
Dictionary<string, List<string>> list = new Dictionary<string, List<string>>();
List<string> propertyList = new List<string>();
Type myType = typeof(Input0Buffer);
PropertyInfo[] allPropInfo = myType.GetProperties();
List<PropertyInfo> SqlPropInfo = allPropInfo.Where(x => !x.Name.Contains("AM_")).ToList();
// Loop through all the Sql Property Info so those without AM_
for (int i = 0; i < SqlPropInfo.Count(); i++)
{
List<string> group = new List<string>();
foreach (var propInfo in allPropInfo)
{
if (propInfo.Name.Contains(SqlPropInfo[i].Name))
{
// Group the values based on the property
// ex. All last names are grouped.
group.Add(propInfo.GetValue(Row, null).ToString());
}
}
// The Key is the Sql's Property Name.
list.Add(SqlPropInfo[i].Name, group);
}
foreach (var item in list)
{
// Do a check if there are two values in both SQL and Oracle.
if (item.Value.Count >= 2)
{
if (item.Value.Count() != item.Value.Distinct().Count())
{
// Duplicates exist do nothing.
}
else
{
// The values are different so update the value[0]. which is the SQL Value.
UpdateRecord(item.Key, item.Value[0], Row.AssociateId);
}
}
}
}
I separated the values from the two tables so there are two lists values from TableA and TableB. You can prefix the values from TableA with "AM_" or something distinct so you can use reflection to to get the properties with and without the prefix and find out which values belong to which table. Then I just loop through the properties and group the values with the properties from the target value (so those without the prefix "AM_") I then loop through the grouped list and compare the two values and if it's different, update TableA with the TableB values to match them
You are already in SSIS so I will propose using that (no matter how quick I usually jump to C# to solve problems)
This is a classic conditional split scenario:
Do your test then run the results into a SQL Update statement.
I am trying to write a program that prints out (in a string variable) the following information about an mdb database:
Table Name
Total number of columns of the table
List of columns as follows:
Column Name:
Column Data Type:
To accomplish this I used two custom types (public classes) and of course, lists. Here is the code I have so far (which by the way has been adjusted not in small part thanks to questions and answers gathered here):
Here are the classes I created to define the two new types I am using:
public class ClmnInfo
{
public string strColumnName { get; set; }
public string strColumnType { get; set; }
}
public class TblInfo
{
public string strTableName { get; set; }
public int intColumnsQty { get; set; }
public List<ClmnInfo> ColumnList { get; set; }
}
Here is the code that actually gets the data. Keep in mind that I am using OleDB to connect to the actual data and everything works fine, except for the problem I will describe below.
As a sample, I am currently testing this code with a simple 1 table db, containing 12 columns of type string save for 1 int32 (Long Int in Access).
//Here I declare and Initialize all relevant variables and Lists
TblInfo CurrentTableInfo = new TblInfo();
ClmnInfo CurrentColumnInfo = new ClmnInfo();
List<TblInfo> AllTablesInfo = new List<TblInfo>();
//This loop iterates through each table obtained and imported previously in the program
int i = 0;
foreach (DataTable dt in dtImportedTables.Tables)
{
CurrentTableInfo.strTableName = Globals.tblSchemaTable.Rows[i][2].ToString(); //Gets the name of the current table
CurrentTableInfo.intColumnsQty = dt.Columns.Count; //Gets the total number of columns in the current table
CurrentTableInfo.ColumnList = new List<ClmnInfo>(); //Initializes the list which will house all of the columns
//This loop iterates through each column in the current table
foreach (DataColumn dc in dt.Columns)
{
CurrentColumnInfo.ColumnName = dc.ColumnName; // Gets the current column name
CurrentColumnInfo.ColumnType = dc.DataType.Name; // Gets the current column data type
CurrentTableInfo.ColumnList.Add(CurrentColumnInfo); // adds the information just obtained as a member of the columns list contained in CurrentColumnInfo
}
//BAD INSTRUCTION FOLLOWS:
AllTablesInfo.Add(CurrentTableInfo); //This SHOULD add The collection of column_names and column_types in a "master" list containing the table name, the number of columns, and the list of columns
}
I debugged the code and watched all variables. It works great (the table name and column quantity gets registered correctly, as well as the list of column_names, column_types for that table), but when the "bad" instruction gets executed, the contents of AllTablesInfo are not at all what they should be.
The table name is correct, as well as the number of columns, and the columns list even has 12 members as it should have, but each member of the list is the same, namely the LAST column of the database I am examining. Can anyone explain to me why CurrentTableInfo gets overwritten in this manner when it is added to the AllTablesInfo list?
You're creating a single TblInfo object, and then changing the properties on each iteration. Your list contains lots of references to the same object. Just move this line:
TblInfo CurrentTableInfo = new TblInfo();
to the inside of the first loop, and this line:
ClmnInfo CurrentColumnInfo = new ClmnInfo();
inside the nested foreach loop, so that you're creating new instances on each iteration.
Next:
Important
Make sure you understand why it was failing before. Read my article on references if you're not sure how objects and references (and value types) work in C#
Use camelCased names instead of CamelCased ones for local variables
Consider using an object initializer for the ClmnInfo
Change your type names to avoid unnecessary abbreviation (TableInfo, ColumnInfo)
Change your property names to avoid pseudo-Hungarian notation, and make them PascalCased
Consider rewriting the whole thing as a LINQ query (relatively advanced)
The pre-LINQ changes would leave your code looking something like this:
List<TableInfo> tables = new List<TableInfo>();
int i = 0;
foreach (DataTable dt in dtImportedTables.Tables)
{
TableInfo table = new TableInfo
{
Name = Globals.tblSchemaTable.Rows[i][2].ToString(),
// Do you really need this? Won't it be the same as Columns.Count?
ColumnCount = dt.Columns.Count,
Columns = new List<ColumnInfo>()
};
foreach (DataColumn dc in dt.Columns)
{
table.Columns.Add(new ColumnInfo {
Name = dc.ColumnName,
Type = dc.DataType.Name
});
}
tables.Add(table);
// I assume you meant to include this?
i++;
}
With LINQ:
List<TableInfo> tables =
dtImportedTables.Tables.Zip(Globals.tblSchemaTable.Rows.AsEnumerable(),
(table, schemaRow) => new TableInfo {
Name = schemaRow[2].ToString(),
// Again, only if you really need it
ColumnCount = table.Columns.Count,
Columns = table.Columns.Select(column => new ColumnInfo {
Name = column.ColumnName,
Type = column.DataType.Name
}).ToList()
}
}).ToList();
You have only created one instance of TblInfo.
It's because you only have a single instance of TblInfo, which you keep updating in your loop and then add another reference to it to the List. Thus your list has many references to the same object in memory.
Move the creation of the CurrentTableInfo instance inside the for loop.
i am currently working with SQL CE & WPF . in the middle of coding i struck with no idea of converting the dataset of a Database to my observablecollection which is binds to the UI Controllers like Listbox and listview.
plz guide me , if possible with code !!
Let's say your DataSet contains a Table named Person and that Person has columns Id, Name, and Age.
You first create a Person class to hold your Person data:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Then you use LINQ to populate your ObservableCollection:
var people = new ObservableCollection<Person>(
dataset.Tables["Person"].AsEnumerable().Select(p => new Person
{
Id = p.Field<int>("Id"),
Name = p.Field<string>("Name"),
Age = p.Field<int>("Age")
}));
You will need to add the following assembly reference to your project in order to use the AsEnumerable<T>() and Field<T>() extension methods:
System.Data.DataSetExtensions (in System.Data.DataSetExtensions.dll)
Edit
In response to your comment, you would normally process each change you make to the data immediately rather than try to convert the whole ObservableCollection back to the DataSet. So, for example, if you add a new Person to your ObservableCollection, you would also want to add that Person to the DataSet.
Add a person:
var table = dataSet.Tables["Person"];
var row = table.NewRow();
row["Id"] = person.Id;
row["Name"] = person.Name;
row["Age"] = person.Age;
table.Rows.Add(row);
Delete a person:
var table = dataSet.Tables["Person"];
var row = table.AsEnumerable().Where(p => p.Id == person.Id);
row.Delete();
Update a person (say you want to change the age to 37):
var table = dataSet.Tables["Person"];
var row = table.AsEnumerable().Where(p => p.Id == person.Id);
var row["Age"] = 37;
You might also want to look into LINQ to SQL because it automates a lot of this stuff.