I have a database table with the following structure:
Columns: DealID (int), CustomerID (int), DocumentArchiveID (int), DealXML (string of XML)
The issue is:
a value for the CustomerID field can appear multiple times in the table but for each time it appears the DealXML associated with it is unique. I need to connect to the table and create a file of the XML contained in the DealXML column - but only one file per CustomerID. So basically if a CustomerID appears 5 times I need to create one file with all the related DealXML data in that file... if a CustomerID appears only once then I create a single file with just that CustomerID's DealXML in it. So at the end of it all I need one file per each unique instance of CustomerID but each file should contain all the DealXML data associated with that particular CustomerID. I am at a complete loss as to how to accomplish this and I'm facing a deadline.
Summary: need to create a file for each unique instance of CustomerID (a CustomerID can appear many times in the table, each time with a distinct DealXML that needs to go into the file) - each file contains all the DealXML for that particular CustomerID.
I thought of creating a FileStream with FileMode.Append, creating a unique file for each unique CustomerID in the database but unfortunately I do not have control over what I name my files (they must adhere to a convention established outside my organization) and cannot use this method to create unique files (based on the CustomerID) which was my first idea.
I'm doing this in .Net platform using C# and a SQL Server 2008 database.
Any help? Anyone? Feedback deeply appreciated.
First, you need a query that brings you back everything in the correct order:
SELECT CustomerID, DealID, DealXML FROM TABLE ORDER BY CustomerID, DealID
Next loop through the results. Every time you encounter a new CustomerID, just create a new file (using whatever conventions you need to) and write the xml (Note that you will have to wrap all of the DealXML values with a root element to create well formed xml):
<customerData>
<DealXML />
<DealXML />
<DealXML />
</customerData>
EDIT: You can do something like this (this is some sketch code - but this gives you the basic idea)... The basic idea is you put the deal xmls into a collection until you move to another customer id.
int previousCustomerId = -1;
List<string> deals = new List<string>();
while(rs.ReadNext())
{
int customerId = rs["CustomerID"];
if (customerId != previousCustomerId)
{
//Don't do this on the first go
if (customerId != -1)
{
//Generate a filename
string filename = GenerateFileName(customerId);
//There are better ways to write multiple values to a file,
// but this should give you an idea of where to start.
File.AppendText(filename, "<customerData>");
//Dump all of the DealXML values to the file
foreach(string deal in deals)
File.AppendText(filename, deal);
File.AppendText(filename, "</customerData>");
}
//Reinitialize the list
deals = new List<string>();
//Save the new customer id
previousCustomerID = customerId;
}
deals.Add((string)rs["DealXML"]);
}
Well, a brute-force approach would be to query for distinct CustomerIDs. If DealXML is nullable, you should select distinct CustomerID from table X where DealXML is not null
Then, loop over the resulting dataset. In each loop, query for the DealXML for the current Customer ID. You'll get back a dataset with 1 or more rows; open a new file, loop thru the dataset, and append to the file.
You'll need to put a wrapper around each customer's XML to be well-formed...
Related
So in this code, the entire database is called GProperty, and I need to access the table called ScannedDocs. If the filename already exists I need to do nothing. 'filename' is the variable of the read in file while 'fileName' is a field in ScannedDocs that stores new filenames in the database. If there is no file that exists I need to give it an id which is why I search for the biggest id and then add 1 to ensure I give the new file a new id.
I just need a few pointers to make sure I'm doing this correctly. Any help is appreciated. Thank You!!
GProperty db = new Gproperty();
List<int> args = (from ScannedDocs in db.ScannedDocs
where filename = fileName
select *).ToList();
if (args.Count() = 0)
{
int i = select MAX(id) from db.ScannedDocs;
db.ScannedDocs.id = i+1;
Depending on which database you're operating on, there should be a way to auto-increment to the max ID from a given table at the moment of an insert. For instance: IDENTITY on MS SQL Server and MySQL. For Oracle, you can use CREATE SEQUENCE.
I have two tables, students and files that have a many-to-many relation.
I have a service that contains an updateStudent method that gets the student's
details including fileIds (as List<guid>), and update them in the database.
The method looks something like this:
var student = context.students.find(id)
...
update student details
...
student.files = **context.files.where(f => fileIds.contains(f.id))**
This line of code:
context.files.where(f => fileIds.contains(f.id))
goes to the database and returns all File's data, including the content (byte array), which I don't really need, because I already have the Id's, and I only want to delete from table studentsFiles all the relevant student file ids and insert the new ones. But for that I don't need the file content. It is unnecessary, and can affect performance.
Do you have any alternative way to only update the many to many relation table with only the ids, without having the entire entry instance?
Thanks in advance
I am using the answer of this question How to automatically generate unique id in sql server to create a custom id for a table.It worked perfectly.Now I have a column which holds the values such as UID00000001 UID00000002 and so on. Suppose the last value in this column is UID00000003.Now I want to calculate the value for the row which hasn't been inserted yet via C# in one of my .aspx pages.In this case UID00000004. How can I achieve this value?
Any help would be appreciated.
Thank you.
If you are not required to generate these identifier at database level (e.g. some other processes insert records there), you can pre-generate them within your application. Something like above:
class Generator
{
public static int UniqueId = 0;
public static int GetNextId()
{
return Interlocked.Increment(ref UniqueId);
}
}
Then, your code can preallocate these identifiers and also format those strings. If multiple users access the same functionality, they will receive other identifiers. However, if one does not (successfully) performs a save operation, those identifiers will be lost.
You need to execute this query to get the next identity which will be generated for the table:
SELECT IDENT_CURRENT('table_name')+1;
For your case, it will have some other info concatenated with the next identity so the query will be like this:
SELECT 'UID' + RIGHT('00000000' + CAST(IDENT_CURRENT('table_name')+1 AS VARCHAR(8)), 8)
Of course you will need to write the C# code to send that query to the SQL Server.
Having said that, keep this in mind: When you get the value from that call and hold onto it, if during the time you are holding the value a record is inserted into that table, then the value is no longer the next value.
If you need the identiy value after a record is inserted in your application, please refer this answer.
At the moment, I source my data from a SQL serve r(2008) database. The cyurrent method is to use a DataTable, which is then passed around and used.
if (parameters != null)
{
SqlDataAdapter _dataAdapter = new SqlDataAdapter(SqlQuery, CreateFORSConnection());
foreach (var param in parameters)
{
_dataAdapter.SelectCommand.Parameters.AddWithValue(param.Name, param.Value);
}
DataTable ExtractedData = new DataTable(TableName);
_dataAdapter.Fill(ExtractedData);
return ExtractedData;
}
return null;
But now, the user has said that we can also get data from txt files, which have the same structure as the tables in SQL Server. So, if I have a table called 'Customer', then I have a csv file with Customer. with the same column structure. The first line in the CSV is the column name, and matches my tables.
Would it be possible to read the txt file into a data table, and then run a SELECT on that data table somehow? Most of my queries are single table queries:
SELECT * FROM Table WHERE Code = 111
There is, however, ONE case where I do a join. That may be a bit more tricky, but I can make a plan. If I can get the txt files into data tables first, I can work with that.
Using the above code, can I not change the connection string to rather read from a CSV instead of SQL Server?
First, you'll need to read the CSV data into a DataTable. There are many CSV parsers out there, but since you prefer using ADO.NET, you can use the OleDB client. See the following article.
http://www.switchonthecode.com/tutorials/csharp-tutorial-using-the-built-in-oledb-csv-parser
Joining is a bit harder, since both sets of data live in different places. But what you can do is get two DataTables (one from each source), then use Linq to join them.
Inner join of DataTables in C#
You could read the text file into a List<string> (if there is just 1 column per file), and then use LINQ to query the list. For example:
var result = from entry in myList
where entry == "111"
select entry;
Of course, this example is kind of useless since all you get back is the same string you are searching for. But if there are multiple columns in the file, and they match the columns in your DataTable, why not read the file into the data table, and then use LINQ to query the table?
Here is a simple tutorial about how to use LINQ to query a DataTable:
http://blogs.msdn.com/b/adonet/archive/2007/01/26/querying-datasets-introduction-to-linq-to-dataset.aspx
I have a table in a SQL database which has a ID column (auto incrementing) and is set to be the primary key. The table consists of this ID and an account name.
I then have a bit of code which reads this table and populates a listview with the data. The problem is, if I order by the account name - I get duplicates listed in the listview. If I order it by the ID, I don't see any duplicates.
The original data in the SQL database contains no duplicate account names, so obviously that's what i'd like to see in the listview.
This is the Linq i'm using to grab the data...
public static IEnumerable<Client2> GetClientList()
{
return (IEnumerable<Client2>)from c in entity.Client2s
orderby c.AccountName
select c;
}
And this is the code which is being used to create the listview...
// Clear the listview
listViewClient.Items.Clear();
// Get imported client list from database
foreach (Client2 c in SQLHandler.GetClientList())
{
ListViewItemClient lvi = new ListViewItemClient(c.AccountName, c);
listViewClient.Items.Add(lvi);
}
As I say, if I change this to orderby c.ID then it returns data as expected. I've also tried adding an index to AccountName. I do use a custom listview item subclass, but all that does is store a reference to the Client object.
Any idea how I can resolve this?
Thanks,
Just to clarify for anyone else potentially reading this issue, it was programmer error. My data did indeed contain duplicates but because of the sort order, they weren't listed together and therefore I didn't see them when manually checking the data. It was only when I started displaying the ID that I realised they weren't sequential.