The connection is already in a transaction and cannot participate in another transaction - ef-core-2.1

I am calling this method:
public IEnumerable<T> ExecuteObject<T>(string query, Func<DbDataReader, T> map)
{
var trx = miContexto.Database.BeginTransaction();
var entities = new List<T>();
miContexto.Database.OpenConnection();
using (var command = miContexto.Database.GetDbConnection().CreateCommand())
{
command.CommandText = query;
command.CommandType = CommandType.Text;
command.Transaction = trx.GetDbTransaction();
using (var result = command.ExecuteReader())
{
while (result.Read())
{
entities.Add(map(result));
}
}
}
trx.Commit();
trx.Dispose();
return entities;
}
From MVC controller by this lines:
var result = c.ExecuteObject(
"SELECT TOP 10 Nombre, Apellido FROM Persona "
+ " GROUP BY Nombre, Apellido ORDER BY Apellido DESC",
x => new Persona {
Nombre = (string)x[0],
Apellido = (string)x[1], });
result.ToList();
return View();
It works most of the time but every often it throws the exception "The connection is already in a transaction and cannot participate in another transaction".
Any ideas. I tried to solve it in many different ways but unsuccessfully.
I used using(transaction scope), using(dbcontext.database.opentransaction). but this exceptions appears with all this options.

Related

SqlDependency failed because A SELECT statement that cannot be notified or was provided

I'm trying to use SqlDependency, And I read articles Creating a Query for Notification, Query Notification Permissions from Microsoft. I double checked many times, it seems all meet what it needs which mentions in articles Here is my code.
private void InitialSqlDependency()
{
using (var connection = new SqlConnection(_connString))
{
connection.Open();
string message = string.Empty;
string query = #"SELECT ModifiedOn FROM [dbo].[ContainerTransactions]";
using (var command = new SqlCommand(query, connection))
{
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(Dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
SqlDataReader dr = command.ExecuteReader();
if (dr.HasRows)
{
dr.Read();
message = dr[0].ToString();
}
}
}
}
private void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
_logger.Debug("ContainerWatch Dependency Fired!");
if (e.Type == SqlNotificationType.Change)
{
_logger.Debug("ContainerWatch Change Fired!");
this.InitialSqlDependency();
}
}
However, It always failed to subscribe. And I see SqlNotificationInfo returns Query which means A SELECT statement that cannot be notified or was provided. Here is my debug img
The SELECT statement is extremely simple, Is there any possible reason causing fail?
I found the root cause, because The statement must not reference tables with computed columns. I use a query below to see computed columns
SELECT * FROM sys.computed_columns WHERE object_id = OBJECT_ID('ContainerTransactions')
Therefore, I think I can't use SqlDependency on this table.

JDBC SQL aliasing not working

I am trying to run the following query in my java web application:
SELECT platform AS "Platform" FROM edb.cases
The web-app is working fine and is able to execute all queries however whenever I use an alias (through 'AS'), the resultant data-set gives me a null value for the alias. In fact, despite using an alias for the column 'platform' in the above query, the resultant data-set has a null value for the key 'Platform' but gives me the correct value for the key 'platform' (which is the original name of the column).
Now the actual sql statement which I need to execute is a bit more complex with select statements and left joins on the same table twice using aliases, like so:
SELECT numOne.platform , numTwo.platform AS 'PlatformTwo' FROM edb.cases LEFT JOIN
edb.platform as numOne ON (numOne.rank = cases.platform) LEFT JOIN edb.platform as numTwo ON
(numTwo.rank = cases.highestPlatform) WHERE cases.index = 1000
The problem is that the resultant data-set contains the correct value for the key 'platform' (for numOne table) but the keys 'PlatformOne' and 'PlatformTwo' DO NOT EXIST. The aliases are not working!
I have tried both the statements in MySql workbench and they work fine.
Please do not hesitate to ask for more information.
EDIT:
The code that prepares the query and sends it to the database:
public static List<Map<String, Object>> executeQuery(final String query,
Map<Integer, Object> data) {
List<Map<String, Object>> result = null;
try {
Connection conn = createConnection();
PreparedStatement pstmt = null;
pstmt = conn.prepareStatement(query);
if(data != null) {
pstmt = createPreparedStatement(pstmt, data);
}
System.out.println(pstmt.toString());
//The GET_CASE_FOR_INDEX query uses the executequery function in the else block:
if((pstmt.toString().indexOf("INSERT") >= 0) || (pstmt.toString().indexOf("UPDATE") >= 0)) {
pstmt.executeUpdate();
} else {
ResultSet rs = pstmt.executeQuery();
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
result = new ArrayList<Map<String, Object>>();
/*
* Get the next row of the ResultSet 'rs' and insert a Map of the Column/Value pair
* into the ArrayList of Maps 'result'
*/
while(rs.next()) {
Map<String, Object> row = new HashMap<String, Object>(columns);
for(int i=1; i <= columns; i++) {
try {
row.put(md.getColumnName(i), rs.getObject(i));
} catch(Exception e) {
System.out.println(md.getColumnName(i));
System.out.println(row);
e.printStackTrace();
}
}
result.add(row);
}
}
destroyConnection(conn);
pstmt.close();
} catch(SQLException e) {
//TODO
e.printStackTrace();
}
return result;
}
The function creating the prepared statement:
//creates a prepared statement by checking the type of the value that needs to be set.
private static PreparedStatement createPreparedStatement(
PreparedStatement pstmt, Map<Integer, Object> data) {
try {
for(Integer key : data.keySet()) {
Object value = data.get(key);
System.out.println(key);
if(data.get(key).equals(Types.NULL)) {
pstmt.setNull(key, Types.INTEGER);
} else if(value.getClass().equals(Integer.class)) {
pstmt.setInt(key, (Integer) value);
} else if(value.getClass().equals(String.class)) {
pstmt.setString(key, (String) value);
} else if(value.getClass().equals(Date.class)) {
pstmt.setDate(key, (Date) value);
} else if(value.getClass().equals(Timestamp.class)) {
pstmt.setTimestamp(key, (Timestamp) value);
}
}
}catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return pstmt;
}
And the code snippet which uses the executeQuery function to execute the query and sends it to the web template:
Map<Integer, Object> data_details = new HashMap<Integer, Object>();
data_details.put(1, parameter_ID);
List<Map<String, Object>> details = DBUtility.executeQuery(DBQuery.GET_CASE_FOR_INDEX, data_details);
webContext.setVariable("details", details);//This is where the template variable is being set
System.out.println(details);
The GET_CASE_FOR_INDEX query is :
SELECT numOne.platform , numTwo.platform AS 'PlatformTwo' FROM edb.cases LEFT JOIN
edb.platform as numOne ON (numOne.rank = cases.platform) LEFT JOIN edb.platform as numTwo ON
(numTwo.rank = cases.highestPlatform) WHERE cases.index = ?
When I print the details hash map (which is the result data-set) the key PlatformTwo is entirely absent!
You are using the .getColumnName method of ResultSetMetaData, which returns the name of the underlying column (if available). .getColumnLabel will return the column alias as defined by SELECT ... AS ....
To illustrate, the following Java code
PreparedStatement ps = conn.prepareStatement(
"SELECT platform AS Platypus FROM cases");
ResultSet rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
System.out.println(String.format(
".getColumnName returns \"%s\"",
rsmd.getColumnName(1)));
System.out.println(String.format(
".getColumnLabel returns \"%s\"",
rsmd.getColumnLabel(1)));
returns
.getColumnName returns "platform"
.getColumnLabel returns "Platypus"

How to get data from database javafx

I have this project and I need to get data (writing) from a database and I am using javaFX. I have a connection class that works (when I run it makes the connection)
public class Conexiune extends JPanel {
public Connection con = null;
public Statement stmt = null;
public ResultSet rs = null;
Vector data = null;
Vector columns = null;
JTable table;
JPanel paneOrar;
JTable tabel;
void login() throws SQLException {
String url = "jdbc:mysql://localhost:3308/database";
String login = "root";
String password = "password";
con = (Connection) DriverManager.getConnection(url, login, password);
}
Component query() throws SQLException {
stmt = con.createStatement();
ResultSet result = stmt.executeQuery("SELECT * FROM data");
ResultSetMetaData md = (ResultSetMetaData) result.getMetaData();
int columnCount = md.getColumnCount();
Vector columns = new Vector(columnCount);
// store column names
for (int i = 1; i <= columnCount; i++)
columns.add(md.getColumnName(i));
Vector data = new Vector();
Vector row;
// store row data
while (result.next()) {
row = new Vector(columnCount);
for (int i = 1; i <= columnCount; i++) {
row.add(result.getString(i));
}
data.add(row);
}
JScrollPane scrollPane = new JScrollPane(tabel);
this.setLayout(null);
JTable table = new JTable(data, columns);
return this.add(table);
}
Conexiune() {
try {
login();
System.out.println("bdConnect");
} catch (SQLException sqle) {
System.err.println(sqle);
}
}
}
After I run I get the message bdConnect with no errors.
The main problem is that i don't know what to do after, I mean I want to get the text from the database on to something that is not a table. Something like a scrollPane. Lets say i just want a window full of text on multiple lines but not a table. Lets say that you want to get the contents of a book from your database, you cant put it in a table. Can anyone help me please I'm getting kind of desperate!!!

Validation for duplicate record

I have some problem when doing validation for my rating system. So basically what I am trying to do is one user only can vote for once for each product, either vote up or vote down and I am doing in 3 tier.
My sql statement to validate for the vote record based on each productID and user name:
public boolean validateRate(){
boolean result = false;
ResultSet rs = null;
DBController db = new DBController();
db.getConnection();
String dbQuery = "SELECT * FROM sm_productrate WHERE productID =" + prodID + " AND custName = '" + custName + "' AND productRateUp = 1 OR productRateDown = 1";
rs = db.readRequest(dbQuery);
try {
if (rs.next()) {
result = true;
}else{
result = false;
}
} catch (Exception e) {
e.printStackTrace();
}
db.terminate();
return result;
}
And this is my submit like and dislike method together with the validate method of the calling of the sql method above:
public boolean submitLike(CreateReviewAndRateUI panel,int row){
String custName = panel.getUserLoggedLbl().getText();
shopManagement.entity.Product product = new shopManagement.entity.Product(row, custName);
boolean result = product.validateRate();
if(result == true){
Dialogs.showErrorDialog(null, "You have already voted once for this product", "Duplicate rate record found", "");
result = true;
}else{
product.submitLike();
result = false;
}
return result;
}
public boolean submitDislike(CreateReviewAndRateUI panel,int row){
String custName = panel.getUserLoggedLbl().getText();
shopManagement.entity.Product product = new shopManagement.entity.Product(row, custName);
boolean result = product.validateRate();
if(result == true){
Dialogs.showErrorDialog(null, "You have already voted once for this product", "Duplicate rate record found", "");
}else{
product.submitDislike();
}
return result;
}
public boolean validateRate(CreateReviewAndRateUI panel, int row){
String custName = panel.getUserLoggedLbl().getText();
Product product = new Product(row, custName);
boolean result = product.validateRate();
return result;
}
And this is when the button on click, it will call the methods above accordingly.
#FXML
public void submitLike(ActionEvent event){
int row = Integer.parseInt(getGetRowLbl().getText());
CreateReviewAndRateController controller = new CreateReviewAndRateController();
boolean result = controller.submitLike(myPane,row);
if(!result){
Dialogs.showInformationDialog(null, "Up vote has been successfully sunmitted",
"Successful Submission", "");
displayRate(row);
getLikeBtn().setDisable(true);
getDislikeBtn().setDisable(true);
}
}
#FXML
public void submitDislike(ActionEvent event){
int row = Integer.parseInt(getGetRowLbl().getText());
CreateReviewAndRateController controller = new CreateReviewAndRateController();
boolean result = controller.submitDislike(myPane,row);
if(!result){
Dialogs.showInformationDialog(null, "Down vote has been successfully sunmitted",
"Successful Submission", "");
displayRate(row);
getLikeBtn().setDisable(true);
getDislikeBtn().setDisable(true);
}
}
However, there's a very strange thing happened. For example, my first user to enter the rate is Dean. Everything works perfectly, it can add the rate record into database, can validate without any problem. But when I change the user logged, and I tried to insert a rate record into database, it does not works, it keeps prompting me the duplicate record found error message but in fact, there's no rate record for the second users in database. Then after that, I log in with the first user which is Dean again, and I choose a product without any rate record. And yet, it does not works as well. I wonder where did I coded wrongly. Hope my explanation for my problem is clear enough.
Thanks in advance.
try this
String dbQuery = "SELECT * FROM sm_productrate WHERE productID =" + prodID +
" AND custName = '" + custName + "' AND (productRateUp = 1 OR productRateDown = 1)";

PgSQL Exception: column name not found

I am using postgresql-8.3-603.jdbc4.jar with jdk 1.6 in my application to do the db operations. I am getting the below exceptions at sometimes and doing restart helps to avoid this exceptions temporarily.
org.postgresql.util.PSQLException: The column name sender_id was not found in this ResultSet.
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.findColumn(AbstractJdbc2ResultSet.java:2502)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getString(AbstractJdbc2ResultSet.java:2345)
at org.apache.commons.dbcp.DelegatingResultSet.getString(DelegatingResultSet.java:225)
at org.apache.commons.dbcp.DelegatingResultSet.getString(DelegatingResultSet.java:225)
at com.netcore.bulkrequest.db.FeedDAO.setFeedDetails(FeedDAO.java:142)
at com.netcore.bulkrequest.feed.Feed.getInstance(Feed.java:37)
at com.netcore.bulkrequest.core.BulkRequestTask.(BulkRequestTask.java:86)
at com.netcore.bulkrequest.core.BulkRequestValidate.getBulkRequestTaskObject(BulkRequestValidate.java:104)
at com.netcore.bulkrequest.core.BulkRequestValidate.run(BulkRequestValidate.java:57)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Here is the code snippet:
public class FeedDAO {
/**
* Database connection pool object
*/
private final DBContext dbc;
private final Feed feed;
public static final String SENDER_ID_ATTRIBUTE = "sender_id";
/**
* Constructor
*
* #param dbc
* #param feed
*/
public FeedDAO(DBContext dbc, Feed feed) {
this.dbc = dbc;
this.feed = feed;
}
public void setFeedDetails() throws SQLException {
String feedDetailsQuery = "SELECT a.priority, b.keyword, b.welcome " +
" FROM feed AS a, pub_feed_info AS b " +
" WHERE a.resource_id = b.resource_id AND b.resource_id = ?";
String senderIdQuery = "SELECT b.attribute_value AS " +
SENDER_ID_ATTRIBUTE + " FROM " +
"attribute_master AS a, feed_attributes AS b " +
"WHERE a.attribute_id = b.attribute " +
" AND a.attribute_name='" + SENDER_ID_ATTRIBUTE + "' " +
" AND feed_id = ?";
Connection con = null;
PreparedStatement fdStmt = null;
PreparedStatement siStmt = null;
try {
con = dbc.getConnection();
//Get the feed details
fdStmt = dbc.getPreparedStatement(con, feedDetailsQuery);
fdStmt.setInt(1, this.feed.getFeedId());
fdStmt.execute();
ResultSet fdResults = fdStmt.getResultSet();
while (fdResults.next()) {
String keyword = fdResults.getString("keyword");
String welcomeMsg = fdResults.getString("welcome");
int priority = fdResults.getInt("priority");
if(null != keyword) {
this.feed.setKeyword(keyword);
} else {
this.feed.setKeyword(String.valueOf(this.feed.getFeedId()));
}
this.feed.setWelcomeMsg(welcomeMsg);
this.feed.setPriority(priority);
}
//Get the sender id
siStmt = dbc.getPreparedStatement(con, senderIdQuery);
siStmt.setInt(1, this.feed.getFeedId());
if(siStmt.execute()) {
ResultSet siResults = siStmt.getResultSet();
while(siResults.next()) {
String senderId = siResults.getString(SENDER_ID_ATTRIBUTE);
this.feed.setSenderId(senderId);
}
} else {
this.feed.setSenderId(Feed.DEFAULT_SENDER_ID);
}
} catch (SQLException ex) {
throw ex;
} finally {
if (fdStmt != null) { fdStmt.close(); }
if (siStmt != null) { siStmt.close(); }
if (con != null) { con.close(); }
}
}
}
Can anyone please help me to find the permanent fix?
Thanks,
Mani
The key part of the error is "The column name sender_id was not found in this ResultSet" -- te very first row. So, how about showing us the query that's looking for a column that's just not there, and maybe the results of executing that query interactively in pgsql, the relevant parts of your schema, etc? Surely you can't expect us to help you debug without seeing anything more than the exception traceback, with zero clues about your code and DB!