I would like one of my table to have row level locking. I am currently using JPA (hibernate) with play framework.
Is this something that needs to be specified at the DB level or can it be done progammatically?
As a work around I ended up setting the transaction to read_uncommited with the code below.
try{
Session session = (Session) Report.em().getDelegate();
Connection connection = session.connection();
connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
} catch(SQLException e){
...
}
This seems to suit my needs but is not exactly what I was looking for.
Furthermore the session.connection() is deprecated and this might not be a long term solution.
Related
We have this web service with the following algorithm (the input is an id and a name)
public bool SetCustomer(int externalId,string name)
{
using (var db = new BusinessEntities())
{
var c = db.Customer.FirstOrDefault(c => c.externalId== externalId) ?? new Customer(){externalId = externalId};
c.name = name;
db.SaveChanges();
}
}
The problem is, if someone calls at the same moment this web service with the same id, then 2 customers are created.
We cannot add a unique constraint, because some other process in the app might create customer with the same externalId.
We thought about a solution with a dictionary of object that would be used as lock argument, but it doesn't seems right.
We don't want to lock the full table customer because we have a lot of parallel calls, so this will cause timeout.
Can you use an intermediate table to log insertion jobs.
Then do the jobs (creating the customer) with a mono threaded task.
This may require an asynchronous solution if your web method has to return a result.
Or even something more elaborated like Asynchronous Triggers from Sql Service Broker.
I found something :
http://michaeljswart.com/2011/09/mythbusting-concurrent-updateinsert-solutions/
it's not with entity framework but I don't think EF provide access to this kind of features.
thanks
I have no Idea about JTA,to understand the overall scenarios please follow this link How to maintain acid property of 3 sequential transaction of three diffrenet databases ,However based on suggestions from the post,I have to use Distributed transactions. I am using apache-tomcat server.
But As I said i have no idea about JTA, So my problem is that, I have more than 15 database connection, and based on the some condition, their respective database is connected. So I can't create hibernate.cfg.xml and session factories and entities for each databases .
So My question is that, can i use JTA with plain jdbc? ,and if possible then provide me some links or examples.
Yes . You can use JTA with plain JDBC . The general idea is that instead of using JDBC Connection object to declare the transaction boundary , you use the Transaction Manager object which is provided by the JTA implementation to declare the transaction boundary .
For example , in the case of Bitronix Transaction Manager , declaring a transaction boundary across many database Connection can be done by the following codes:
PoolingDataSource derbyDataSource1 = new PoolingDataSource();
derbyDataSource1.setClassName("org.apache.derby.jdbc.EmbeddedXADataSource");
derbyDataSource1.setUniqueName("derby1");
derbyDataSource1.getDriverProperties().setProperty("databaseName", "database1");
derbyDataSource1.init();
PoolingDataSource derbyDataSource2= new PoolingDataSource();
derbyDataSource2.setClassName("org.apache.derby.jdbc.EmbeddedXADataSource");
derbyDataSource2.setUniqueName("derby2");
derbyDataSource2.getDriverProperties().setProperty("databaseName", "database2");
derbyDataSource2.init();
BitronixTransactionManager btm = TransactionManagerServices.getTransactionManager();
btm.begin();
try {
Connection c1= derbyDataSource1.getConnection();
Connection c2= derbyDataSource2.getConnection();
/***Use c1 and c2 to execute statements again their corresponding DBs as usual**/
btm.commit();
} catch (SQLException ex) {
ex.printStackTrace();
btm.rollback();
}
I have created Backup of my in-memory database using the below code:
public static void backUpDatabase(Connection conn)throws SQLException
{
String backupdirectory ="c:/mybackups/"+JCalendar.getToday();
CallableStatement cs = conn.prepareCall("CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE(?)");
cs.setString(1, backupdirectory);
cs.execute();
cs.close();
System.out.println("backed up database to "+backupdirectory);
}
Now I want to restore the database by creating an In-memory database from the previous backup. How should I do it?
Thanks.
The fastest way I am aware of:
First, use shutdown=true:
boolean gotSQLExc = false;
try {
DriverManager.getConnection("jdbc:derby:memory:testdb;shutdown=true");
} catch (SQLException se) {
if ( se.getSQLState().equals("08006") )
System.out.println("Database shut down normally");
else
System.out.println("Database did not shut down normally")
}
Then restoreFrom=
Connection connection = DriverManager.getConnection("jdbc:derby:memory:testdb;restoreFrom=path/to/backup/file");
connection.close();
A db containing ~300 tables with some sample data restored in ~150ms on my dev machine this way.
This is really useful for junit integration testing where fast fast db restore is needed. Depending on your setup, you may need to perform some additional work in-between tests, for example if using c3p0 connection pool, you need to get all connections from C3P0Registry and call hardReset() after this restore. On the other hand, nothing needs to be done with some other pools.
As far as I know, the normal restore-from-backup mechanisms will work just fine to restore an in-memory database. So use the restoreFrom clause on your connection URL, as described here: http://db.apache.org/derby/docs/10.9/adminguide/tadminhubbkup44.html
What is the way to use Sql Server's table hints like "NOLOCK" while using LINQ?
For example I can write "SELECT * from employee(NOLOCK)" in SQL.
How can we write the same using LINQ?
Here's how you can apply NOLOCK: http://www.hanselman.com/blog/GettingLINQToSQLAndLINQToEntitiesToUseNOLOCK.aspx
(Quote for posterity, all rights reserved by mr scott):
ProductsNewViewData viewData = new ProductsNewViewData();
using (var t = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions {
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
}))
{
viewData.Suppliers = northwind.Suppliers.ToList();
viewData.Categories = northwind.Categories.ToList();
}
I STRONGLY recommend reading about SQL Server transaction isolation modes before using ReadUncommitted.
Here's a very good read
http://blogs.msdn.com/b/davidlean/archive/2009/04/06/sql-server-nolock-hint-other-poor-ideas.aspx
In many cases level ReadSnapshot should suffice. Also you if You really need it You can set default transaction isolation level for Your database by using
Set Transaction Isolation Level --levelHere
Other good ideas include packaging Your context in a wrapper that encapsulates each call using demanded isolation level. (maybe You need nolock 95% of the time and serializable 5% of the time). It can be done using using extension methods, or normal methods by code like:
viewData.Categories = northwind.Categories.AsReadCommited().ToList();
Which takes your IQueryable and does the trick mentioned by Rob.
Hope it helps
Luke
I've done some searching and also read the FAQ on the SQLite site, no luck finding an answer to my question.
It could very well be that my database approach is flawed, but at the moment, I would like to store my data in multiple SQLite3 databases, so that means separate files. I am very worried about data corruption due to my application possibly crashing, or a power outage in the middle of changing data in my tables.
In order to ensure data integrity, I basically need to do this:
begin transaction
modify table(s) in database #1
modify table(s) in database #2
commit, or rollback if error
Is this supported by SQLite? Also, I am using sqlite.net, specifically the latest which is based on SQLite 3.6.23.1.
UPDATE
One more question -- is this something people would usually add to their unit tests? I always unit test databases, but have never had a case like this. And if so, how would you do it? It's almost like you have to pass another parameter to the method like bool test_transaction, and if it's true, throw an exception between database accesses. Then test after the call to make sure the first set of data didn't make it into the other database. But maybe this is something that's covered by the SQLite tests, and should not appear in my test cases.
Yes transactions works with different sqlite database and even between sqlite and sqlserver. I have tried it couple of times.
Some links and info
From here - Transaction between different data sources.
Since SQLite ADO.NET 2.0 Provider supports transaction enlistement, not only it is possible to perform a transaction spanning several SQLite datasources, but also spanning other database engines such as SQL Server.
Example:
using (DbConnection cn1 = new SQLiteConnection(" ... ") )
using (DbConnection cn2 = new SQLiteConnection(" ... "))
using (DbConnection cn3 = new System.Data.SqlClient.SqlConnection( " ... ") )
using (TransactionScope ts = new TransactionScope() )
{
cn1.Open(); cn2.Open(); cn3.Open();
DoWork1( cn1 );
DoWork2( cn2 );
DoWork3( cn3 );
ts.Complete();
}
How to attach a new database:
SQLiteConnection cnn = new SQLiteConnection("Data Source=C:\\myfirstdatabase.db");
cnn.Open();
using (DbCommand cmd = cnn.CreateCommand())
{
cmd.CommandText = "ATTACH DATABASE 'c:\\myseconddatabase.db' AS [second]";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT COUNT(*) FROM main.myfirsttable INNER JOIN second.mysecondtable ON main.myfirsttable.id = second.mysecondtable.myfirstid";
object o = cmd.ExecuteScalar();
}
Yes, SQLite explicitly supports multi-database transactions (see https://www.sqlite.org/atomiccommit.html#_multi_file_commit for technical details). However, there is a fairly large caveat. If the database file is in WAL mode, then:
Transactions that involve changes against multiple ATTACHed databases
are atomic for each individual database, but are not atomic across all
databases as a set.