mst + .msi table information.
I created following function to read msi Tables
// This method returns all rows and columns of a Table specified by Name
public DataTable ReadMsiTableByName(string msiFile, string tableName)
{
DataTable msiTable = new DataTable(tableName);
Database database = null;
View view = null;
try
{
using (database = new Database(msiFile, DatabaseOpenMode.ReadOnly))
{
string sqlQuery = String.Format("SELECT * FROM {0}", tableName);
view = database.OpenView(sqlQuery);
view.Execute(null);
Record record = view.Fetch();
ColumnCollection columnCollection = view.Columns;
for (int i = 0; i < columnCollection.Count; i++)
{
string columnName = columnCollection[i].Name.ToString();
System.Type columnType = columnCollection[i].Type;
msiTable.Columns.Add(columnName, columnType.UnderlyingSystemType);
}
while (record != null)
{
DataRow row = msiTable.NewRow();
for (int i = 0; i < columnCollection.Count; i++)
{
string type = columnCollection[i].Type.ToString();
if (type == "System.String")
{
row[columnCollection[i].Name.ToString()] = record.GetString(columnCollection[i].Name.ToString());
}
else if (type == "System.Int16")
{
row[columnCollection[i].Name.ToString()] = record.GetInteger(columnCollection[i].Name.ToString());
}
else if (type == "System.Int32")
{
row[columnCollection[i].Name.ToString()] = record.GetInteger(columnCollection[i].Name.ToString());
}
else if (type == "System.IO.Stream")
{
System.IO.Stream stream;
stream = record.GetStream(columnCollection[i].Name.ToString());
row[columnCollection[i].Name.ToString()] = stream;
}
}
msiTable.Rows.Add(row);
record = view.Fetch();
}
}
}
catch (Exception ex)
{
CommonFn.CreateLog(ex.ToString());
}
finally
{
if (database != null)
database.Close();
if (view != null)
view.Close();
}
return msiTable;
}
However I am unable to read .mst with this function. I read that you need to use msi transform for it, But I don't want to change the content of msi or mst, I just need to read all the tables. Please point me in right direction. Thanks in Advance :)
An MST is by definition a transform. It only contains the deltas of a base MSI.
The database class has a method called ViewTransform. If the MST is compatible with the MSI it'll succeed and the changes appear in the _TransformView table.
Alternatively if you don't want to see whats changed but you want to see the final state, you could copy the MSI to a temporary MSI and use the ApplyTransform method to apply the transform and then commit it. Now you could query it using the code you already have.
Works for me:
msiDatabase = new Database(#"Foo.msi", DatabaseOpenMode.ReadOnly);
msiDatabase.ApplyTransform(#"Foo.mst");
Related
I just want to retrieve data from a Firebase to DataGridView. The code I have is retrieving data already, however, it's retrieving everything to the same row instead of creating a new one. I'm a beginner in coding, so I really need help with that.
I read online that Firebase doesn't "Count" data, so it'd be needed to create a counter, so each time I add or delete data, an update would be needed. I did it and it's working. I created a method to load the data.
private async Task firebaseData()
{
int i = 0;
FirebaseResponse firebaseResponse = await client.GetAsync("Counter/node");
Counter_class counter = firebaseResponse.ResultAs<Counter_class>();
int foodCount = Convert.ToInt32(counter.food_count);
while (true)
{
if (i == foodCount)
{
break;
}
i++;
try
{
FirebaseResponse response2 = await client.GetAsync("Foods/0" + i);
Foods foods = response2.ResultAs<Foods>();
this.dtGProductsList.Rows[0].Cells[0].Value = foods.menuId;
this.dtGProductsList.Rows[0].Cells[1].Value = foods.name;
this.dtGProductsList.Rows[0].Cells[2].Value = foods.image;
this.dtGProductsList.Rows[0].Cells[3].Value = foods.price;
this.dtGProductsList.Rows[0].Cells[4].Value = foods.discount;
this.dtGProductsList.Rows[0].Cells[5].Value = foods.description;
}
catch
{
}
}
MessageBox.Show("Done");
}
OBS: A DataTable exists already(dataTable), there's a DataGridView too which has columns(ID,Name, Image, Price, Discount, Description), which match the number and order given to the .Cells[x]. When the Form loads, dtGProductsList.DataSource = dataTable; I tried replacing [0] for [i].
I expect the data that is beeing retrieved to be set to a new row and not to the same, and to not skip rows. I'm sorry if it's too simple, but I can't see a way out.
I Faced the same problem and here is mu solution :
Counter_class XClass = new Counter_class();
FirebaseResponse firebaseResponse = await client.GetAsync("Counter/node");
string JsTxt = response.Body;
if (JsTxt == "null")
{
return ;
}
dynamic data = JsonConvert.DeserializeObject<dynamic>(JsTxt);
var list = new List<XClass >();
foreach (var itemDynamic in data)
{
list.Add(JsonConvert.DeserializeObject<XClass >
(((JProperty)itemDynamic).Value.ToString()));
}
// Now you have a list you can loop through to put it at any suitable Visual
//control
foreach ( XClass _Xcls in list)
{
Invoke((MethodInvoker)delegate {
DataGridViewRow row(DataGridViewRow)dg.Rows[0].Clone();
row.Cells[0].Value =_Xdcls...
row.Cells[1].Value =Xdcls...
row.Cells[2].Value =Xdcls...
......
dg.Insert(0, row);
}
I'm trying to insert documents to a table in a DB, but I continue to get this error:
Operand type clash: varbinary (max) is incompatible with text
any direction would be extremely helpful.
The Document table has many columns, I only picked these two thinking I don't need all 50 columns which majority of them are null; both columns are set as (text, null) as the majority of the columns all (text, null).
I am hoping that I don't need to change anything to the database and that there is a way to change the code so that the files can populate correctly to the Documents table.
Here is my HttpPost:
[HttpPost]
public void UploadFiles()
{
if (!(Request.Files?.Count > 0)) return;
var filesCount = Request.Files.Count;
try
{
for (int i = 0; i < filesCount; i++)
{
var file = Request.Files[i];
var fileName = Path.GetFileName(file?.FileName);
if (fileName != null)
{
var fileBytes = new byte[file.InputStream.Length];
file.InputStream.Read(fileBytes, 0, fileBytes.Length);
file.InputStream.Close();
var cmdStr = "insert into [dbo].[Documents]
(DocumentName, DocumentLink) values(#val,#filename)";
using (var connection = new SqlConnection(con))
{
connection.Open();
var cmd = new SqlCommand(cmdStr, connection);
cmd.Parameters.AddWithValue("#val", fileBytes);
cmd.Parameters.AddWithValue("#filename", fileName);
cmd.ExecuteNonQuery();
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
I am using C# to create a SQL Server view, then open an access database and link the table into access. The create view statement, open database statement and link statement work great BUT the catch here is it will always link the table as read-only. What piece o'code do I need to add or update current so that the view is not always linked as read-only?
string MasterDatabase = "R:\\Testing\\MasterDatabase.mdb";
DAO.Database dd;
DAO.DBEngine db = new DAO.DBEngine();
DAO.TableDef tdf9;
bool found = false;
DAO.TableDef tdf1;
string Table = "ServiceEntranceLog";
string TableAccess = "Service_Entrance_Log";
using (var connection = new SqlConnection(ConnectionStringHere))
using (var command = connection.CreateCommand())
{
using (var command4 = connection.CreateCommand())
{
command4.CommandText = "CREATE VIEW HelperView" AS SELECT * FROM monster.ServiceEntranceLog";
command4.ExecuteNonQuery();
}
}
if (_combobox1.SelectedItems.Contains("MasterDatabase"))
{
dd = db.OpenDatabase(CRDB);
try
{
string[] tableNames = new string[1] { TableAccess };
for (int q = tableNames.GetLowerBound(0); q <= tableNames.GetUpperBound(0); q++)
{
foreach (DAO.TableDef tabledef in dd.TableDefs)
{
string name = tableNames[q];
if (tabledef.Name == name) { found = true; }
try { if (found) { dd.TableDefs.Delete(name); } }
catch { }
}
}
}
catch { }
tdf1 = dd.CreateTableDef(TableAccess);
tdf1.Connect = connectionString;
tdf1.SourceTableName = Table;
dd.TableDefs.Append(tdf1);
}
Alritey, so it seems the issue is I needed to define a primary key when linking in the table into access so that the table would be updateable. Using this syntax does the trick
dd.Execute "CREATE UNIQUE INDEX SomeIndex ON SomeTable (PrimaryKeyColumn) WITH PRIMARY"
I wrote a very simple method. It saves data from class DayWeather to the database. Method checks if line with that day exist in table and update her or create a new line.
I am doing it by adding new class for LINQ and move table from Server Inspector to the constructor. It generate new class WeatherTBL.
Method itself looks like this:
public static void SaveDayWeather(DayWeather day)
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
var existingDay =
(from d in db.WeatherTBL
where d.DateTime.ToString() == day.Date.ToString()
select d).SingleOrDefault<WeatherTBL>();
if (existingDay != null)
{
existingDay.Temp = day.Temp;
existingDay.WindSpeed = day.WindSpeed;
existingDay.Pressure = day.Pressure;
existingDay.Humidity = day.Humidity;
existingDay.Cloudiness = day.Cloudiness;
existingDay.TypeRecip = day.TypeRecip;
db.SubmitChanges();
}
else
{
WeatherTBL newDay = new WeatherTBL();
newDay.DateTime = day.Date;
newDay.Temp = day.Temp;
newDay.WindSpeed = day.WindSpeed;
newDay.Pressure = day.Pressure;
newDay.Humidity = day.Humidity;
newDay.Cloudiness = day.Cloudiness;
newDay.TypeRecip = day.TypeRecip;
db.WeatherTBL.InsertOnSubmit(newDay);
db.SubmitChanges();
}
}
}
When I tried to call him from UnitTest project:
[TestMethod]
public void TestDataAccess()
{
DayWeather day = new DayWeather(DateTime.Now);
DataAccessClass.SaveDayWeather(day);
}
It write, that test has passed successfully. But if look into table, it has`t chanched.
No error messages shows. Does anyone know whats the problem?
P.S. Sorry for my bad English.
UDP
Problem was in that:
"...db maybe copied to the debug or release folder at every build, overwriting your modified one". Thanks #Silvermind
I wrote simple method to save employee details into Database.
private void AddNewEmployee()
{
using (DataContext objDataContext = new DataContext())
{
Employee objEmp = new Employee();
// fields to be insert
objEmp.EmployeeName = "John";
objEmp.EmployeeAge = 21;
objEmp.EmployeeDesc = "Designer";
objEmp.EmployeeAddress = "Northampton";
objDataContext.Employees.InsertOnSubmit(objEmp);
// executes the commands to implement the changes to the database
objDataContext.SubmitChanges();
}
}
Please try with lambda expression. In your code, var existingDay is of type IQueryable
In order to insert or update, you need a variable var existingDay of WeatherTBL type.
Hence try using below..
var existingDay =
db.WeatherTBL.SingleOrDefault(d => d.DateTime.Equals(day.Date.ToString()));
if(existingDay != null)
{
//so on...
}
Hope it should work..
Linq to SQL
Detail tc = new Detail();
tc.Name = txtName.Text;
tc.Contact = "92"+txtMobile.Text;
tc.Segment = txtSegment.Text;
var datetime = DateTime.Now;
tc.Datetime = datetime;
tc.RaisedBy = Global.Username;
dc.Details.InsertOnSubmit(tc);
try
{
dc.SubmitChanges();
MessageBox.Show("Record inserted successfully!");
txtName.Text = "";
txtSegment.Text = "";
txtMobile.Text = "";
}
catch (Exception ex)
{
MessageBox.Show("Record inserted Failed!");
}
I have a ProductLevel table in an SQL database. It contains the products for a store. I want to copy these records into a ProductLevelDaily table at the time the user logs onto the hand held device in the morning.
As they scan items the bool goes from false to true so at anytime they can see what items are left to scan/check.
From the mobile device I pass the siteID and date to the server:
int userID = int.Parse(oWebRequest.requestData[5]); and a few other things
IEnumerable<dProductLevelDaily> plditems
= DSOLDAL.CheckProductDailyLevelbySiteCount(siteID, currentDate);
This checks if there are any records already moved into this table for this store. Being the first time this table should be empty or contain no records for this store on this date.
if (plditems.Count() == 0) // is 0
{
IEnumerable<dProductLevel> ppitems = DSOLDAL.GetProductsbySite(siteID);
// this gets the products for this store
if (ppitems.Count() > 0)
{
dProduct pi = new dProduct();
foreach (dProductLevel pl in ppitems)
{
// get the product
pi = DSOLDAL.getProductByID(pl.productID, companyID);
dProductLevelDaily pld = new dProductLevelDaily();
pld.guid = Guid.NewGuid();
pld.siteID = siteID;
pld.statusID = 1;
pld.companyID = companyID;
pld.counted = false;
pld.createDate = DateTime.Now;
pld.createUser = userID;
pld.productID = pl.productID;
pld.name = "1000"; // pi.name;
pld.description = "desc"; // pi.description;
DSOLDAL.insertProductLevelDailyBySite(pld);
}
}
}
On the PDA the weberequest response returns NULL
I can't see what the problem is and why it wont work.
The insert is in DSOLDAL:
public static void insertProductLevelDailyBySite(dProductLevelDaily pld)
{
dSOLDataContext dc = new dSOLDataContext();
try
{
dc.dProductLevelDailies.InsertOnSubmit(pld);
// dProductLevelDailies.Attach(pld, true);
dc.SubmitChanges();
}
catch (Exception exc)
{
throw new Exception(getExceptionMessage(exc.Message));
}
finally
{
dc = null;
}
}
This code works until I put the foreach loop inside with the insert
IEnumerable<dProductLevelDaily> plditems
= DSOLDAL.CheckProductDailyLevelbySiteCount(siteID, s);
if (plditems.Count() == 0) // plditems.Count() < 0)
{
IEnumerable<dProductLevel> ppitems = DSOLDAL.GetProductsbySite(siteID);
if (ppitems.Count() > 0)
{
oWebResponse.count = ppitems.Count().ToString();
oWebResponse.status = "OK";
}
else
{
oWebResponse.count = ppitems.Count().ToString();
oWebResponse.status = "OK";
}
}
else
{
oWebResponse.count = "2"; // plditems.Count().ToString();
oWebResponse.status = "OK";
}
These kind of bulk operations aren't very well matched to what Linq-to-SQL does.
In my opinion, I'd do this using a stored procedure, which you could include in your Linq-to-SQL DataContext and call from there.
That would also leave the data on the server and just copy it from one table to the other, instead of pulling down all data to your client and re-uploading it to the server.
Linq-to-SQL is a great tool - for manipulating single objects or small sets. It's less well suited for bulk operations.