Entity Framework Slow Closing Connection - sql-server

I am builing an MVC 5 web app and I am using entity framework 6 and I have MS SQL Server 2008 R2 as my database. I use connection pooling to ensure that I get a connection as fast as possible for db operations. My connection string in my Web.config is as follows
<add name="MyConnectionPoolConnectionString" connectionString="Data Source=MyHOST;Initial Catalog=TEST_DB;User Id=sa;Password=password1; Min Pool Size=10;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
I notice that obtaining a connection from the connection pool is very fast i.e. some tens to hundreds of milliseconds
However, what I have also noticed is that closing the connection (which in a connection pool means the connection is returned to the pool) takes a rather long time (i.e. on the average between 2000ms and 5000ms (2 - 5 secs)).
Here is an excerpt from my profiling log
Time taken to open connection
2015-02-18 21:06:55,497 Opened connection at 18/02/2015 21:06:55 92.65 ms
Time taken to close / return connection
Closed connection at 18/02/2015 21:07:01 2543.06 ms
Notice that opening the connection takes 92ms and closing the connection takes 2500ms.
BTW, these stats are provided my the EF framework itself i.e. by setting the Log property of the Database prop on the EF context i.e.
MyTestAppDbContext.Database.Log = Logger.Debug;
What I dont understand is why it is so fast to get a connection from the connection pool but it takes so long for EF to return the connection back to the pool (i.e. close the connection) and more importantly how to speed up the release/closing of the connection
This is quite important for me because the web app needs to be quite responsive and as I have to create the EF Dbcontext for every request, if EF adds an extra 2 - 5 secs overhead to just close / release a connection, it reduces the responsiveness of the app.
MyTestAppDbContext.cs
public partial class MyTestAppDbContext : DbContext
{
public ILogger Logger { get; set; }
static MyTestAppDbContext()
{
System.Data.Entity.Database.SetInitializer<MyTestAppDbContext>(null);
}
public MyTestAppDbContext(ILogger logger)
: base("Name=MyConnectionPoolConnectionString")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
Logger = logger;
this.Database.Log = Logger.Debug;
}
public override int SaveChanges()
{
Exception entityFrameworkExceptions = null;
String exMsg = "";
int result = 0;
try
{
if (this.ChangeTracker.HasChanges())
{
// Get all Added/Deleted/Modified entities (not Unmodified or Detached)
foreach (var ent in this.ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified))
{
// For each changed record, log the activity performed
Logger.Debug("Detected Changes");
}
result = base.SaveChanges();
}
}
catch (DbEntityValidationException dbEx)
{
entityFrameworkExceptions = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
//System.Diagnostics.Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
exMsg += String.Format("\nProperty: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
Logger.Debug(String.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));
}
}
}
catch (DbUpdateException dbEx)
{
entityFrameworkExceptions = dbEx;
Logger.Debug(String.Format("Exception Message: {0}", dbEx.Message));
Logger.Debug(String.Format("InnerException: {0}", dbEx.InnerException));
Logger.Debug(String.Format("StackTrace: {0}", dbEx.StackTrace));
Logger.Debug(String.Format("Call Stack: {0}", CommonUtils.GetCallStackAsString()));
}
catch (Exception ex)
{
entityFrameworkExceptions = ex;
Logger.Debug(String.Format("Exception Message: {0}", ex.Message));
Logger.Debug(String.Format("InnerException: {0}", ex.InnerException));
Logger.Debug(String.Format("StackTrace: {0}", ex.StackTrace));
Logger.Debug(String.Format("Call Stack: {0}", CommonUtils.GetCallStackAsString()));
}
if (entityFrameworkExceptions != null)
{
exMsg = exMsg + "\n" + entityFrameworkExceptions.Message + #"\n" + entityFrameworkExceptions.StackTrace + #"\n" + entityFrameworkExceptions.InnerException;
entityFrameworkExceptions = new HttpException(500, #"Exception applying changes in PaceDBContext (i.e. Entity Framework)\n" + exMsg+"\n"+CommonUtils.GetCallStackAsString());
throw entityFrameworkExceptions;
}
return result;
}
}
IUnitOfWork.cs
public interface IUnitOfWork /*: IDisposable*/
{
MyTestAppDbContext MyTestAppDbContext { get; set; }
Exception Save();
}
UnitOfWork.cs
public class UnitOfWork : IUnitOfWork, IDisposable
{
private bool disposed = false;
public MyTestAppDbContext MyTestAppDbContext {get; set;}
public ILogger Logger { get; set; }
public Exception Save()
{
Exception entityFrameworkExceptions = null;
String exMsg = "";//, callStackAsString = "";
try
{
System.Diagnostics.Trace.TraceInformation("Saving Db Changes in UnitOfWork");
MyTestAppDbContext.SaveChanges();
System.Diagnostics.Trace.TraceInformation("Finished saving Db Changes in UnitOfWork");
}
catch (DbEntityValidationException dbEx)
{
entityFrameworkExceptions = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
exMsg += String.Format("\nProperty: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
Logger.Debug(String.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));
}
}
}
catch (DbUpdateException dbEx)
{
entityFrameworkExceptions = dbEx;
this.LogException(dbEx);
}
catch (Exception ex)
{
entityFrameworkExceptions = ex;
this.LogException(ex);
}
if (entityFrameworkExceptions != null)
{
exMsg = "\n" + entityFrameworkExceptions.Message + #"\n" + entityFrameworkExceptions.StackTrace + #"\n" + entityFrameworkExceptions.InnerException+"\n"+CommonUtils.GetCallStackAsString();
entityFrameworkExceptions = new HttpException(500, #"Exception applying changes in PaceDBContext (i.e. Entity Framework)\n" + exMsg);
throw entityFrameworkExceptions;
}
return entityFrameworkExceptions;
}
protected virtual void Dispose(bool disposing)
{
this.Save();
if (!this.disposed)
{
if (disposing)
{
MyTestAppDbContext.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void LogException(Exception ex){
Logger.Debug(String.Format("Exception Message: {0}", ex.Message));
Logger.Debug(String.Format("InnerException: {0}", ex.InnerException));
Logger.Debug(String.Format("StackTrace: {0}", ex.StackTrace));
}
}
UserRepository.cs
public class UserRepository : IUserRepository
{
public IUnitOfWork UnitOfWork { get; private set; }
public UserRepository(IUnitOfWork unitOfWork)
{
this.UnitOfWork = unitOfWork;
}
public Users GetUserByUserId(string userId)
{
if (!String.IsNullOrEmpty(userId)){
var user = from u in UnitOfWork.MyTestAppDbContext.Users
where u.UserId.Trim().Equals(userId.Trim())
select u;
return user.SingleOrDefault();
}
return null;
}
public string GetUserFullName(string userId)
{
string fullname = null;
if (!String.IsNullOrEmpty(userId))
{
var user = (from u in UnitOfWork.MyTestAppDbContext.Users
where u.UserId.Trim().Equals(userId.Trim())
select u).SingleOrDefault();
if (user != null)
{
if (!String.IsNullOrEmpty(user.FirstName))
fullname += user.FirstName + " ";
if (!String.IsNullOrEmpty(user.LastName))
fullname += user.LastName;
}
}
return fullname;
}
public long GetUserGroupId(string userId)
{
if (!String.IsNullOrEmpty(userId))
{
var user = (from u in UnitOfWork.MyTestAppDbContext.Users
where u.UserId.Trim().Equals(userId.Trim())
select u).SingleOrDefault();
if (user != null)
return user.UserGroupId;
}
return -1;
}
}
Thanks

Related

BaseX parrallel Client

I have client like this :
import org.basex.api.client.ClientSession;
#Slf4j
#Component(value = "baseXAircrewClient")
#DependsOn(value = "baseXAircrewServer")
public class BaseXAircrewClient {
#Value("${basex.server.host}")
private String basexServerHost;
#Value("${basex.server.port}")
private int basexServerPort;
#Value("${basex.admin.password}")
private String basexAdminPassword;
#Getter
private ClientSession session;
#PostConstruct
private void createClient() throws IOException {
log.info("##### Creating BaseX client session {}", basexServerPort);
this.session = new ClientSession(basexServerHost, basexServerPort, UserText.ADMIN, basexAdminPassword);
}
}
It is a singleton injected in a service which run mulitple queries like this :
Query query = client.getSession().query(finalQuery);
return query.execute();
All threads query and share the same session.
With a single thread all is fine but with multiple thread I get some random (and weird) error, like the result of a query to as a result of another.
I feel that I should put a synchronized(){} arround query.execute() or open and close session for each query, or create a pool of session.
But I don't find any documentation how the use the session in parrallel.
Is this implementation fine for multithreading (and my issue is comming from something else) or should I do it differently ?
I ended creating a simple pool by adding removing the client from a ArrayBlockingQueue and it is working nicely :
#PostConstruct
private void createClient() throws IOException {
log.info("##### Creating BaseX client session {}", basexServerPort);
final int poolSize = 5;
this.resources = new ArrayBlockingQueue < ClientSession > (poolSize) {
{
for (int i = 0; i < poolSize; i++) {
add(initClient());
}
}
};
}
private ClientSession initClient() throws IOException {
ClientSession clientSession = new ClientSession(basexServerHost, basexServerPort, UserText.ADMIN, basexAdminPassword);
return clientSession;
}
public Query query(String finalQuery) throws IOException {
ClientSession clientSession = null;
try {
clientSession = resources.take();
Query result = clientSession.query(finalQuery);
return result;
} catch (InterruptedException e) {
log.error("Error during query execution: " + e.getMessage(), e);
} finally {
if (clientSession != null) {
try {
resources.put(clientSession);
} catch (InterruptedException e) {
log.error("Error adding to pool : " + e.getMessage(), e);
}
}
}
return null;
}

Extent report version 4 - Create two extent reports instead of one html report for all extectued testcases

I am using extent reportversion 4 and want one .html report after executing of all the testcases but it creates two html reports for executing the 3 methods in testclass
In the testclass, I have writteh code like that #beforemethod will execute before executing each testcase, followed by executing the testcase & in #aftermethod it will flush the repot to generate Html report and afterthat using #afterclass annotations to quit the driver**
**Testclass:**
public class HomePageTest extends BaseClass {
HomePage homePage;
public HomePageTest() {
super();
}
#BeforeMethod
#Parameters({ "platformName", "url", "udid" })
public void setUpHomePageClass(String platformName, String url, String udid) throws Exception {
try {
BaseClass baseClass = new BaseClass();
baseClass.initialize_driver(platformName, url, udid);
homePage = new HomePage(driver);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
#BeforeMethod
#Parameters({ "platformName", "url", "udid" })
public void setUpHomePageClass(String platformName, String url, String udid) throws Exception {
try {
BaseClass baseClass = new BaseClass();
baseClass.initialize_driver(platformName, url, udid);
homePage = new HomePage(driver);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Test(priority = 1, description = "Verify element i.e Top50 Txt on homepage test")
#Severity(SeverityLevel.NORMAL)
#Description("TestCase Description: Verify element i.e Top50 Txt on homepage")
public void verifyeElementsOnHomePageTest() throws Exception {
log.info("***Executing verifyElementsOnHomeScreenTest***");
logger = extent.createTest("Verify the elements on HomePage after redirecting to the splash screen");
log.info("wait for continue_button to be clickable");
TestUtil.waitForElementToBeClickable(By.id("continue_button"));
homePage.clickContinueBtnAfterSplashScreen();
log.info("Clicked on continue_button");
log.info("waitForUserNameToBeClickable - username");
boolean flag = homePage.validateTop50Txt();
Assert.assertTrue(flag);
log.info("Top50Txt isDisplayed");
log.info("verifyElementsonHomeScreenTest Ended");
}
#Test(priority = 2, description = "Swipe to next video test")
#Severity(SeverityLevel.NORMAL)
#Description("TestCase Description: Swipe from one video to another")
public void swipeToNxtVideoTest() throws InterruptedException {
try {
logger = extent.createTest("Swipe from one video to another & get the username ");
log.info("***Executing swipeToNxtVideoTest***");
log.info("waitForElementToPresenceOfElementLocated - username");
TestUtil.waitForElementToPresenceOfElementLocated(By.id("user_name"));
log.info("swipeverticalDown for nxt video");
TestUtil.swipeverticalDown();
log.info("swipeToNxtVideoTest Ended");
} catch (Exception e) {
e.printStackTrace();
log.error("Found Exception - swipeToNxtVideoTest");
}
}
/*
* #Test(priority = 3, retryAnalyzer =
* com.automation.listeners.RetryAnalyzer.class ) public void checkFailure() {
* Assert.assertEquals(true, false); System.out.println("failed");
*
* }
*/
#AfterMethod
public void getResult(ITestResult result) throws Exception {
if (result.getStatus() == ITestResult.FAILURE) {
logger.log(Status.FAIL,
MarkupHelper.createLabel(result.getName() + " - Test Case Failed", ExtentColor.RED));
logger.log(Status.FAIL,
MarkupHelper.createLabel(result.getThrowable() + " - Test Case Failed", ExtentColor.RED));
String screenshotPath = TestUtil.captureScreenAsBase64(driver, result.getName());
logger.fail("Snapshot below: " + logger.addScreenCaptureFromPath(screenshotPath));
} else if (result.getStatus() == ITestResult.SKIP) {
logger.log(Status.SKIP,
MarkupHelper.createLabel(result.getName() + " - Test Case Skipped", ExtentColor.ORANGE));
} else if (result.getStatus() == ITestResult.SUCCESS) {
logger.log(Status.PASS,
MarkupHelper.createLabel(result.getName() + " Test Case PASSED", ExtentColor.GREEN));
}
extent.flush();
}
#AfterClass
public void quitDriver() {
getDriver().quit();
}
Please do let me know where I have been lacking in code; I might have a intuitions that there is an issue in testng annotations in my code
Base Class:
DesiredCapabilities capabilities = new DesiredCapabilities();
public void setDriver(AppiumDriver<MobileElement> driver) {
tdriver.set(driver);
}
public static synchronized AppiumDriver<MobileElement> getDriver() {
return tdriver.get();
}
public BaseClass() {
try {
prop = new Properties();
FileInputStream ip = new FileInputStream(
System.getProperty("user.dir") + "/src/main/java/com/automation/config/config.properties");
prop.load(ip);
// extend reports
Date date = new Date();
SimpleDateFormat dateFormatFolder = new SimpleDateFormat("dd_MMM_yyyy");
File ResultDir = new File(System.getProperty("user.dir") + File.separator + "/FrameworkReports/"
+ dateFormatFolder.format(date));
// Defining Directory/Folder Name
if (!ResultDir.exists()) { // Checks that Directory/Folder Doesn't Exists!
ResultDir.mkdir();
}
SimpleDateFormat dateFormat = new SimpleDateFormat("dd_MMM_yyyy_hh_mm_ssaa");
htmlReporter = new ExtentHtmlReporter(
ResultDir + "/" + "Report" + " " + dateFormat.format(date) + " .html");
htmlReporter.config().setDocumentTitle("Automation Report");
htmlReporter.config().setReportName("YOVO AUTOMATION");
htmlReporter.config().setTheme(Theme.DARK);
extent = new ExtentReports();
extent.attachReporter(htmlReporter);
extent.setSystemInfo("Host Name", "localhost");
extent.setSystemInfo("Environment", "Windows 7");
extent.setSystemInfo("User Name", "Abhishek Chauhan");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void initialize_driver(String platformName, String url, String udid) throws Exception {
log = LogManager.getLogger(BaseClass.class);
BasicConfigurator.configure();
File appDir = new File("/src/main/resources/apk");
File app = new File(appDir, "yovoapp-release.apk");
mDirpath = System.getProperty("user.dir");
mApkfilepath = mDirpath + "/app/yovoapp-release.apk";
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, platformName);
capabilities.setCapability(MobileCapabilityType.UDID, udid);
switch (platformName) {
case "Android":
capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60);
capabilities.setCapability("appPackage", prop.getProperty("androidAppPackage"));
capabilities.setCapability("appActivity", prop.getProperty("androidAppActivity"));
capabilities.setCapability("app", mApkfilepath);
capabilities.setCapability("noReset", true);
driver = new AppiumDriver<MobileElement>(new URL(url), capabilities);
// tdriver.set(driver);
// return getDriver();
case "IOS":
File classpathRoot = new File(System.getProperty("user.dir"));
// File appDir = new File(classpathRoot, "/build/");
// File app = new File(appDir, "WordPress.app");
capabilities.setCapability("platformVersion", "9.2");
capabilities.setCapability("deviceName", "iPhone 6");
capabilities.setCapability("app", app.getAbsolutePath());
// driver = new IOSDriver<MobileElement>(new
// URL("http://127.0.0.1:4723/wd/hub"), caps);
break;
default:
throw new Exception("Invalid platform! - " + platformName);
}
setDriver(driver);
}

How to connect to SQL Server from .Net Core without using Entity Framework?

How can we connect to SQL Server from .Net Core without using Entity Framework?
you can simply use the traditional way which use SqlConnection
here is an example
public class BaseDataAccess
{
protected string ConnectionString { get; set; }
public BaseDataAccess()
{
}
{
public BaseDataAccess(string connectionString)
private SqlConnection GetConnection()
this.ConnectionString = connectionString;
}
{
if (connection.State != ConnectionState.Open)
SqlConnection connection = new SqlConnection(this.ConnectionString);
connection.Open();
return connection;
SqlCommand command = new SqlCommand(commandText, connection as SqlConnection);
}
protected DbCommand GetCommand(DbConnection connection, string commandText, CommandType commandType)
{
protected SqlParameter GetParameter(string parameter, object value)
command.CommandType = commandType;
return command;
}
{
parameterObject.Direction = ParameterDirection.Input;
SqlParameter parameterObject = new SqlParameter(parameter, value != null ? value : DBNull.Value);
return parameterObject;
}
SqlParameter parameterObject = new SqlParameter(parameter, type); ;
protected SqlParameter GetParameterOut(string parameter, SqlDbType type, object value = null, ParameterDirection parameterDirection = ParameterDirection.InputOutput)
{
if (type == SqlDbType.NVarChar || type == SqlDbType.VarChar || type == SqlDbType.NText || type == SqlDbType.Text)
{
}
parameterObject.Size = -1;
}
parameterObject.Direction = parameterDirection;
if (value != null)
{
parameterObject.Value = value;
}
else
{
parameterObject.Value = DBNull.Value;
}
return parameterObject;
DbCommand cmd = this.GetCommand(connection, procedureName, commandType);
protected int ExecuteNonQuery(string procedureName, List<DbParameter> parameters, CommandType commandType = CommandType.StoredProcedure)
{
int returnValue = -1;
try
{
using (SqlConnection connection = this.GetConnection())
{
if (parameters != null && parameters.Count > 0)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
using (DbConnection connection = this.GetConnection())
returnValue = cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
//LogException("Failed to ExecuteNonQuery for " + procedureName, ex, parameters);
throw;
}
return returnValue;
}
protected object ExecuteScalar(string procedureName, List<SqlParameter> parameters)
{
object returnValue = null;
try
{
{
}
DbCommand cmd = this.GetCommand(connection, procedureName, CommandType.StoredProcedure);
if (parameters != null && parameters.Count > 0)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
returnValue = cmd.ExecuteScalar();
}
}
catch (Exception ex)
{
//LogException("Failed to ExecuteScalar for " + procedureName, ex, parameters);
throw;
return returnValue;
}
ds = cmd.ExecuteReader(CommandBehavior.CloseConnection);
protected DbDataReader GetDataReader(string procedureName, List<DbParameter> parameters, CommandType commandType = CommandType.StoredProcedure)
{
DbDataReader ds;
try
{
DbConnection connection = this.GetConnection();
{
DbCommand cmd = this.GetCommand(connection, procedureName, commandType);
if (parameters != null && parameters.Count > 0)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
}
}
catch (Exception ex)
{
}
//LogException("Failed to GetDataReader for " + procedureName, ex, parameters);
throw;
}
return ds;
}
More can be find here
Update
you have to add nuget package
Install-Package System.Data.SqlClient
that is still confusing for me... .Net Core & .Net standard vs regular .Net: How do we know which packages we can use with .Net core?
Dependencies means that what you should have installed on your machine in order to use the package or nuget will install it for you
to understand more how dependencies work in .net take a look here
Note
that if the nuget package target .net standard library mostly work on both .net core and .net standard framework
If you surprised with BaseDataAccess class format in another answer and referenced article same as me, here is well formatted example... hopefully it will save you some time
public class BaseDataAccess
{
protected string ConnectionString { get; set; }
public BaseDataAccess()
{
}
public BaseDataAccess(string connectionString)
{
this.ConnectionString = connectionString;
}
private SqlConnection GetConnection()
{
SqlConnection connection = new SqlConnection(this.ConnectionString);
if (connection.State != ConnectionState.Open)
connection.Open();
return connection;
}
protected DbCommand GetCommand(DbConnection connection, string commandText, CommandType commandType)
{
SqlCommand command = new SqlCommand(commandText, connection as SqlConnection);
command.CommandType = commandType;
return command;
}
protected SqlParameter GetParameter(string parameter, object value)
{
SqlParameter parameterObject = new SqlParameter(parameter, value != null ? value : DBNull.Value);
parameterObject.Direction = ParameterDirection.Input;
return parameterObject;
}
protected SqlParameter GetParameterOut(string parameter, SqlDbType type, object value = null, ParameterDirection parameterDirection = ParameterDirection.InputOutput)
{
SqlParameter parameterObject = new SqlParameter(parameter, type); ;
if (type == SqlDbType.NVarChar || type == SqlDbType.VarChar || type == SqlDbType.NText || type == SqlDbType.Text)
{
parameterObject.Size = -1;
}
parameterObject.Direction = parameterDirection;
if (value != null)
{
parameterObject.Value = value;
}
else
{
parameterObject.Value = DBNull.Value;
}
return parameterObject;
}
protected int ExecuteNonQuery(string procedureName, List<DbParameter> parameters, CommandType commandType = CommandType.StoredProcedure)
{
int returnValue = -1;
try
{
using (SqlConnection connection = this.GetConnection())
{
DbCommand cmd = this.GetCommand(connection, procedureName, commandType);
if (parameters != null && parameters.Count > 0)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
returnValue = cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
//LogException("Failed to ExecuteNonQuery for " + procedureName, ex, parameters);
throw;
}
return returnValue;
}
protected object ExecuteScalar(string procedureName, List<SqlParameter> parameters)
{
object returnValue = null;
try
{
using (DbConnection connection = this.GetConnection())
{
DbCommand cmd = this.GetCommand(connection, procedureName, CommandType.StoredProcedure);
if (parameters != null && parameters.Count > 0)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
returnValue = cmd.ExecuteScalar();
}
}
catch (Exception ex)
{
//LogException("Failed to ExecuteScalar for " + procedureName, ex, parameters);
throw;
}
return returnValue;
}
protected DbDataReader GetDataReader(string procedureName, List<DbParameter> parameters, CommandType commandType = CommandType.StoredProcedure)
{
DbDataReader ds;
try
{
DbConnection connection = this.GetConnection();
{
DbCommand cmd = this.GetCommand(connection, procedureName, commandType);
if (parameters != null && parameters.Count > 0)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
ds = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
}
catch (Exception ex)
{
//LogException("Failed to GetDataReader for " + procedureName, ex, parameters);
throw;
}
return ds;
}
}
Here is a solution for an ASP.NET MVC Core 3.1 project tested in Visual Studio 2019 community edition.
Create a small database in SQL Express.
Then add a few lines to appsettings.json for the connection strings:
"ConnectionStrings": {
//PROD on some server
"ProdConnection": "Server=somePRODServerofYours;Database=DB_xxxxx_itemsubdb;User Id=DB_xxxxx_user;Password=xxsomepwdxx;Integrated Security=false;MultipleActiveResultSets=true;encrypt=true",
//DEV on localhost
"DevConnection": "Server=someDEVServerofYours;Database=DB_xxxxx_itemsubdb;User Id=DB_xxxxx_user;Password=xxsomepwdxx;Integrated Security=false;MultipleActiveResultSets=true;"
},
Then use code similar to the following in your controller ....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using System.Data.SqlClient;
using System.Data;
namespace SomeNameSpace.Controllers
{
//This Model class should be saved somewhere else in your project.
//It is placed here for simplicity.
public class XtraSimpleContent
{
public string UserName { get; set; }
public string References { get; set; }
public string CreatedTime { get; set; }
}
public class CodeNotesController : Controller
{
public IConfiguration Configuration { get; }
public string connStr = String.Empty;
public CodeNotesController(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
if (env.IsDevelopment())
{
connStr = Configuration.GetConnectionString("DevConnection");
}
else
{
connStr = Configuration.GetConnectionString("ProdConnection");
}
}
[HttpGet]
public async Task<IActionResult> CodeActionMethodToConnectToSQLnetCore()
{
//add using System.Data.SqlClient;
// using System.Data;
//Along with the using statements, you need the system assembly reference.
//To add assembly you can do the following.
// install nuget package. Right Click on Project > Manage Nuget Packages >
// Search & install 'System.Data.SqlClient' and make sure it is compatible with the type of project (Core/Standard);
List<XtraSimpleContent> aListOfItems = new List<XtraSimpleContent>();
string commandText = #"SELECT * FROM [dbo].[ItemSubmissions]
WHERE SUBMITTEREMAIL = #SUBMITTEREMAIL
ORDER BY CreationDatetime DESC";
using (var connection = new SqlConnection(connStr))
{
await connection.OpenAsync(); //vs connection.Open();
using (var tran = connection.BeginTransaction())
{
using (var command = new SqlCommand(commandText, connection, tran))
{
try
{
command.Parameters.Add("#SUBMITTEREMAIL", SqlDbType.NVarChar);
command.Parameters["#SUBMITTEREMAIL"].Value = "me#someDomain.org";
SqlDataReader rdr = await command.ExecuteReaderAsync(); // vs also alternatives, command.ExecuteReader(); or await command.ExecuteNonQueryAsync();
while (rdr.Read())
{
var itemContent = new XtraSimpleContent();
itemContent.UserName = rdr["RCD_SUBMITTERNAME"].ToString();
itemContent.References = rdr["RCD_REFERENCES"].ToString();
itemContent.CreatedTime = rdr["CreationDatetime"].ToString();
aListOfItems.Add(itemContent);
}
await rdr.CloseAsync();
}
catch (Exception Ex)
{
await connection.CloseAsync()
string msg = Ex.Message.ToString();
tran.Rollback();
throw;
}
}
}
}
string totalinfo = string.Empty;
foreach (var itm in aListOfItems)
{
totalinfo = totalinfo + itm.UserName + itm.References + itm.CreatedTime;
}
return Content(totalinfo);
}
}
}
Test it with something like:
https://localhost:44302/CodeNotes/CodeActionMethodToConnectToSQLnetCore
With UkrGuru.SqlJson package
appsettings.json:
"ConnectionStrings": {
"SqlJsonConnection": "Server=localhost;Database=SqlJsonDemo;Integrated Security=SSPI"
}
Startup.cs
services.AddSqlJson(Configuration.GetConnectionString("SqlJsonConnection"));
DbController.cs
[ApiController]
[Route("api/[controller]")]
public class DbController : ControllerBase
{
private readonly string _prefix = "api.";
private readonly DbService _db;
public DbController(DbService db) => _db = db;
[HttpGet("{proc}")]
public async Task<string> Get(string proc, string data = null)
{
try
{
return await _db.FromProcAsync($"{_prefix}{proc}", data);
}
catch (Exception ex)
{
return await Task.FromResult($"Error: {ex.Message}");
}
}
[HttpPost("{proc}")]
public async Task<dynamic> Post(string proc, [FromBody] dynamic data = null)
{
try
{
return await _db.FromProcAsync<dynamic>($"{_prefix}{proc}",
(object)data == null ? null : data);
}
catch (Exception ex)
{
return await Task.FromResult($"Error: {ex.Message}");
}
}
}

Use Memcache in Dataflow: NullPointerException at NamespaceManager.get

I am trying to access GAE Memcache and Datastore APIs from Dataflow.
I have followed How to use memcache in dataflow? and setup Remote API https://cloud.google.com/appengine/docs/java/tools/remoteapi
In my pipeline I have written
public static void main(String[] args) throws IOException {
RemoteApiOptions remApiOpts = new RemoteApiOptions()
.server("xxx.appspot.com", 443)
.useApplicationDefaultCredential();
RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(remApiOpts);
try {
DatastoreConfigManager2.registerConfig("myconfig");
final String topic = DatastoreConfigManager2.getString("pubsub.topic");
final String stagingDir = DatastoreConfigManager2.getString("dataflow.staging");
...
bqRows.apply(BigQueryIO.Write
.named("Insert row")
.to(new SerializableFunction<BoundedWindow, String>() {
#Override
public String apply(BoundedWindow window) {
// The cast below is safe because CalendarWindows.days(1) produces IntervalWindows.
IntervalWindow day = (IntervalWindow) window;
String dataset = DatastoreConfigManager2.getString("dataflow.bigquery.dataset");
String tablePrefix = DatastoreConfigManager2.getString("dataflow.bigquery.tablenametemplate");
String dayString = DateTimeFormat.forPattern("yyyyMMdd")
.print(day.start());
String tableName = dataset + "." + tablePrefix + dayString;
LOG.info("Writing to BigQuery " + tableName);
return tableName;
}
})
where DatastoreConfigManager2 is
public class DatastoreConfigManager2 {
private static final DatastoreService DATASTORE = DatastoreServiceFactory.getDatastoreService();
private static final MemcacheService MEMCACHE = MemcacheServiceFactory.getMemcacheService();
static {
MEMCACHE.setErrorHandler(ErrorHandlers.getConsistentLogAndContinue(Level.INFO));
}
private static Set<String> configs = Sets.newConcurrentHashSet();
public static void registerConfig(String name) {
configs.add(name);
}
private static class DatastoreCallbacks {
// https://cloud.google.com/appengine/docs/java/datastore/callbacks
#PostPut
public void updateCacheOnPut(PutContext context) {
Entity entity = context.getCurrentElement();
if (configs.contains(entity.getKind())) {
String id = (String) entity.getProperty("id");
String value = (String) entity.getProperty("value");
MEMCACHE.put(id, value);
}
}
}
private static String lookup(String id) {
String value = (String) MEMCACHE.get(id);
if (value != null) return value;
else {
for (String config : configs) {
try {
PreparedQuery pq = DATASTORE.prepare(new Query(config)
.setFilter(new FilterPredicate("id", FilterOperator.EQUAL, id)));
for (Entity entity : pq.asIterable()) {
value = (String) entity.getProperty("value"); // use last
}
if (value != null) MEMCACHE.put(id, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return value;
}
public static String getString(String id) {
return lookup(id);
}
}
When my pipeline runs on Dataflow I get the exception
Caused by: java.lang.NullPointerException
at com.google.appengine.api.NamespaceManager.get(NamespaceManager.java:101)
at com.google.appengine.api.memcache.BaseMemcacheServiceImpl.getEffectiveNamespace(BaseMemcacheServiceImpl.java:65)
at com.google.appengine.api.memcache.AsyncMemcacheServiceImpl.doGet(AsyncMemcacheServiceImpl.java:401)
at com.google.appengine.api.memcache.AsyncMemcacheServiceImpl.get(AsyncMemcacheServiceImpl.java:412)
at com.google.appengine.api.memcache.MemcacheServiceImpl.get(MemcacheServiceImpl.java:49)
at my.training.google.common.config.DatastoreConfigManager2.lookup(DatastoreConfigManager2.java:80)
at my.training.google.common.config.DatastoreConfigManager2.getString(DatastoreConfigManager2.java:117)
at my.training.google.mss.pipeline.InsertIntoBqWithCalendarWindow$1.apply(InsertIntoBqWithCalendarWindow.java:101)
at my.training.google.mss.pipeline.InsertIntoBqWithCalendarWindow$1.apply(InsertIntoBqWithCalendarWindow.java:95)
at com.google.cloud.dataflow.sdk.io.BigQueryIO$Write$Bound$TranslateTableSpecFunction.apply(BigQueryIO.java:1496)
at com.google.cloud.dataflow.sdk.io.BigQueryIO$Write$Bound$TranslateTableSpecFunction.apply(BigQueryIO.java:1486)
at com.google.cloud.dataflow.sdk.io.BigQueryIO$TagWithUniqueIdsAndTable.tableSpecFromWindow(BigQueryIO.java:2641)
at com.google.cloud.dataflow.sdk.io.BigQueryIO$TagWithUniqueIdsAndTable.processElement(BigQueryIO.java:2618)
Any suggestions? Thanks in advance.
EDIT: my functional requirement is building a pipeline with some configurable steps based on datastore entries.

javaFX : How to periodically load information from db and show it on a Label?

I want to execute a method periodically, this method get informations from database it show it into a label, I tried the following code :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//update information
miseAjour();
}
}, 0, 2000);
when i run the main program, the background service run also normaly but when the informations changes on db i get this exception:
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
And this is the code of method miseAjour :
public void miseAjour(){
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
int nbrAderent = rs.getInt("nbrAderent");
rs.close();
stmt.close();
connect.commit();
connect.close();
main_nbrAdrTot.setText(nbrAderent + "");
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
}
You can Timer for this, but I would recommend to use the JavaFX provided API called as ScheduledService.
ScheduledService is made to execute the same Task at regular intervals and since it creates a Task internally, there are API which help you to bind the value to the UI controls.
ScheduledService<Object> service = new ScheduledService<Object>() {
protected Task<Object> createTask() {
return new Task<Object>() {
protected Object call() {
// Call the method and update the message
updateMessage(miseAjour());
return object; // Useful in case you want to return data, else null
}
};
}
};
service.setPeriod(Duration.seconds(10)); //Runs every 10 seconds
//bind the service message properties to your Label
label.textProperty().bind(service.messageProperty()); // or use your label -> main_nbrAdrTot
Inside the dbcall method miseAjour, return the value that you have fetched and you want to update the label with :
public String miseAjour(){
String nbrAderent = null;
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
return nbrAderent;
}
Finnaly i resolved the problem ,here is the code :
public class TimerServiceApp {
public void start() throws Exception {
TimerService service = new TimerService();
service.setPeriod(Duration.seconds(10));
service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t) {
main_nbrAdrTot.setText(t.getSource().getMessage());
}
});
service.start();
}
private class TimerService extends ScheduledService<Integer> {
private final StringProperty nbrTotAderent = new SimpleStringProperty();
public final void setTotalAderentNumber(String value ) {
nbrTotAderent.set(value);
}
public String getTotalAderentNumber() throws SQLException {
String nbrAderent = null;
ResultSet rs=null;
Statement stmt=null;
Connection connect=null;
try {
dbConnection db = new dbConnection();
connect = db.connectiondb();
connect.setAutoCommit(false);
stmt= connect.createStatement();
rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
System.out.println(" Total aderent number updated to :" + nbrAderent + " Aderents ");
return nbrAderent;
}
protected Task<Integer> createTask() {
return new Task<Integer>() {
protected Integer call() throws SQLException {
nbrTotAderent.setValue(getTotalAderentNumber());
updateMessage(getTotalAderentNumber());
return Integer.parseInt(getTotalAderentNumber());
}
};
}
}
} `
and i called this service by :
TimerServiceApp s = new TimerServiceApp();
s.start();
i dont know if the solution is optimised but it work :) thank you #ItachiUchiha i took the solution from yout answer in the following link

Resources