DataAdapter .Update does not update back table - c#

my problem is very common, but I have not found any solution.
This is my code:
public async Task<QueryResult> RollbackQuery(ActionLog action)
{
var inputParameters = JsonConvert.DeserializeObject<Parameter[]>(action.Values);
var data = DeserailizeByteArrayToDataSet(action.RollBackData);
using (var structure = PrepareStructure(action.Query, action.Query.DataBase, inputParameters))
{
//_queryPlanner is the implementor for my interface
return await _queryPlanner.RollbackQuery(structure, data);
}
}
I need to load DataTable (from whereever) and replace data to database. This is my Rollback function. This function use a "CommandStructure" where I've incapsulated all SqlClient objects. PrepareStructure initialize all objects
//_dataLayer is an Helper for create System.Data.SqlClient objects
//ex: _dataLayer.CreateCommand(preSelect) => new SqlCommand(preSelect)
private CommandStructure PrepareStructure(string sql, string preSelect, DataBase db, IEnumerable<Parameter> inputParameters)
{
var parameters = inputParameters as IList<Parameter> ?? inputParameters.ToList();
var structure = new CommandStructure(_logger);
structure.Connection = _dataLayer.ConnectToDatabase(db);
structure.SqlCommand = _dataLayer.CreateCommand(sql);
structure.PreSelectCommand = _dataLayer.CreateCommand(preSelect);
structure.QueryParameters = _dataLayer.CreateParemeters(parameters);
structure.WhereParameters = _dataLayer.CreateParemeters(parameters.Where(p => p.IsWhereClause.HasValue && p.IsWhereClause.Value));
structure.CommandBuilder = _dataLayer.CreateCommandBuilder();
structure.DataAdapter = new SqlDataAdapter();
return structure;
}
So, my function uses SqlCommandBuilder and DataAdapter to operate on Database.
PreSelectCommand is like "Select * from Purchase where CustomerId = #id"
The table Purchase has one primaryKey on ID filed
public virtual async Task<QueryResult> RollbackQuery(CommandStructure cmd, DataTable oldData)
{
await cmd.OpenConnectionAsync();
int record = 0;
using (var cmdPre = cmd.PreSelectCommand as SqlCommand)
using (var dataAdapt = new SqlDataAdapter(cmdPre))
using (var cmdBuilder = new SqlCommandBuilder(dataAdapt))
{
dataAdapt.UpdateCommand = cmdBuilder.GetUpdateCommand();
dataAdapt.DeleteCommand = cmdBuilder.GetDeleteCommand();
dataAdapt.InsertCommand = cmdBuilder.GetInsertCommand();
using (var tbl = new DataTable(oldData.TableName))
{
dataAdapt.Fill(tbl);
dataAdapt.FillSchema(tbl, SchemaType.Source);
tbl.Merge(oldData);
foreach (DataRow row in tbl.Rows)
{
row.SetModified();
}
record = dataAdapt.Update(tbl);
}
}
return new QueryResult
{
RecordAffected = record
};
}
I Execute the code and I don't have any errors, but the data are not updated.
variable "record" contain the right number of modified (??) record, but..... on the table nothing
can someone help me?
EDIT 1:
With SQL Profiler I saw that no query is executed on DB. Only select query on .Fill(tbl) command.
EDIT 2:
Now I have made one change:
tbl.Merge(oldData) => tbl.Merge(oldData, true)
so I see perform the expected query but, with reversed parameters.
UPDATE Purchase SET price=123 where id=6 and price=22
instead of
UPDATE Purchase SET price=22 where id=6 and price=123

Related

How to configure BulkInsert to insert as many records as it can and behave fuzzy?

I'm using EF Core Bulk Extensions library. And this is the code that I use to insert a list of entities:
var entities = new List<Enttiy>();
for (var i = 0; i < 1000; i++)
{
var entity = new Entity();
// setting properties
entities.Add(entity);
}
using context = new DatabaseCotnext();
context.BulkInsert(entities);
The problem is that even if one record can not be inserted, it does not insert anything at all.
I don't want it to act transactionally and atomically. I want it to insert as many records as it can. For example, 900 out of 1000.
Is that possible?
Update:
In MariaDB and C#, this code works in a fuzzy manner:
public List<string> BulkInsert(List<T> entities)
{
var problems = new List<string>();
var table = entities.ToTable();
var connectionString = ConnectionString;
if (!connectionString.Contains("AllowLoadLocalInfile"))
{
connectionString = $"{connectionString};AllowLoadLocalInfile=true;";
}
using var connection = new MySqlConnection(connectionString);
connection.InfoMessage += (s, e) =>
{
foreach (var item in e.Errors)
{
problems.Add(item.Message);
}
};
connection.Open();
var bulkCopy = new MySqlBulkCopy(connection);
bulkCopy.DestinationTableName = TableName;
try
{
var result = bulkCopy.WriteToServer(table);
return problems;
}
catch (MySqlException ex)
{
Logger.LogException(ex);
Logger.LogError(problems.Merge());
throw new ServerException(ex.Message + ". See the logs for the list of problems. Also make sure your database schema, specially column orders is correct. And make sure that you use FakerHelper for correct formatting.");
}
}

Problems with linq in getting data from list

I have problem
I need to get list from list in linq. But it type of list is unknown on compilation stage.
using(var context = MyDbContext())
{
var list = (from p in context.Employee select p).ToList()
}
I dont know what just property (change Employee)
I want to do something that
public IList<T> GetAll(string propName)
{
using (var context = new ModelContext())
{
return (from p in context.GetType().GetProperty(propName) select p).ToList();
}
}
The DbContext.Database property provides an API that allows you to perform ADO.NET operations directly. The GetDbConnection method returns a DbConnection object representing the context's underlying connection. From that point, you can revert to the familiar ADO.NET APIs:
public dynamic GetAll(string propName)
{
using (var context = new SampleContext())
using (var command = context.Database.GetDbConnection().CreateCommand())
{
//Escape propName to prevent SQL injection
var builder = new SqlCommandBuilder();
string escapedTableName = builder.QuoteIdentifier(propName);
command.CommandText = $"SELECT * From {escapedTableName}";
context.Database.OpenConnection();
using (var dataReader= command.ExecuteReader())
{
var dataTable = new DataTable();
dataTable.Load(dataReader);
return dataTable ;
}
}
}

ArgumentException: Either orderId or origClientOrderId must be sent

Hi I'm working on Binance API for getting data but I'm not able to get data from getorder api. Link for APi (https://github.com/sonvister/Binance).
I've attached a image of error I'm getting as not aware of this issue.
public void Binance()
{
sqlConnection Conn = new sqlConnection();
Conn.LoadConnection();
Console.WriteLine("Connection Loaded.");
var apiClient = new ApiClient(apiKey, secretKey);
var binanceClient = new BinanceClient(apiClient);
var AllSymbol = binanceClient.GetAllPrices();
foreach (var symbol in AllSymbol.Result)
{
var Orders = binanceClient.GetOrder("BNBBTC").Result;
DataTable ltblAskOrdersHistory =
Orders.Asks.ToList().ToDataTable();
DataColumn column = new DataColumn("Symbol", typeof(string));
column.DefaultValue = symbol.Symbol;
ltblAskOrdersHistory.Columns.Add(column);
Conn.CreateTable("tbBinanceAskOrder");
Conn.ImportRecordsToTable(ltblAskOrdersHistory, "tbBinanceAskOrder");
Console.WriteLine("Ask Orders Table Updated.");
}
}
solved it as:
var Orders = binanceClient.GetAllOrders(symbol.Symbol).Result;
if (Orders.Count() > 0)
{
DataTable ltblOrders = Orders.ToList().ToDataTable();
Conn.CreateTable("tbBinanceOrder");
Conn.ImportRecordsToTable(ltblOrders, "tbBinanceOrder");
Console.WriteLine("tbBinanceOrder Table Updated.");
}

DataSet not saving the data

This is the first time I am using DataSet. Below is my code
var transactionSet = new ModelExecutionContext()
{
TransactionSet = new DataSet()
{
Tables = { new DataTable()
{
TableName = "transaction_history"
}
}
}
};
transactionSet.TransactionSet.Tables["transaction_history"].Columns.Add().ColumnName = "retailer_reference_id";
var retailerReferenceIdRow = transactionSet.TransactionSet.Tables["transaction_history"].NewRow();
retailerReferenceIdRow["retailer_reference_id"] = 8;
transactionSet.TransactionSet.AcceptChanges();
I am unit testing a method in a class which has the datasets. I am trying to mock those datasets. I thought transactionSet.TransactionSet.AcceptChanges(); will save the changes into the DataSet, but in the execution, I am getting context?.TransactionSet?.Tables["transaction_history"]?.Rows.Count = 0
Is anything incorrect with my code?
After you created object of row you need to add row to table.
transactionSet.TransactionSet.Tables["transaction_history"].Rows.Add(retailerReferenceIdRow);

How to get multiple inserted identity values in Entity Framework

I am inserting values in to the table QueryList
[QueryID] [WorkItemID] [RaisedBy]
1 123 xyz
2 234 abc
where QueryID is an Identity column.
I am using a foreach loop and inserting more than one value at a time. My question is how to get all the newly inserted Identity values in Entity Framework 3.5
This is my code
using (TransactionScope currentScope = new TransactionScope())
{
Query newQuery = new Query();
foreach (long workItemId in workItemID)
{
newQuery = new Query();
...
currentScope.Complete();
success = true;
}
}
entityCollection.SaveChanges(true);
int QueryID = newQuery.QueryID; //It gives me last 1 Identity value
You have to track each newly created Query object separately. I suggest using a List<Query> for simplicity:
using (TransactionScope curentScope = new TransactionScope())
{
List<Query> newQueries = new List<Query>();
Query newQuery = new Query();
newQueries.Add(newQuery);
foreach (long workItemId in workItemID)
{
newQuery = new Query();
newQueries.Add(newQuery);
...
curentScope.Complete();
success = true;
}
}
entityCollection.SaveChanges(true);
var queryIDs = newQueries.Select(q => q.QueryID);
Side note: In your code sample you created a Query object outside of the for-loop, but didn't use it at all. This may just be because it's just a sample, but if you use it or insert it in your data context, don't create it.

Categories

Resources