Here is my sample code:
public static class MySqlHelper
{
private static string constring = ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString;
public static int ExecuteNonQuery(string mysqlquery)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(mysqlquery, conn);
int result;
try
{
conn.Open();
result= cmd.ExecuteNonQuery();
}
finally
{
conn.Close();
}
return result;
}
}
Usage: MySqlHelper.ExecuteNonQuery("select * from customers");
I would like to know the issues using this static class.
I can change my class as mentioned here but I have been using this class in couple of websites and I will need couple days to change it in every place and test it out.
Thanks for any inputs.
Edit: Updated the code. Does that make difference on the answers provided? Sorry, I should have posted in the beginning.
I am assuming the connection string doesnt change during execution (you might want to make it readonly). Since there is no other shared state shown in the question, there are no real problems.
However, if you have any shared state you have a huge threading problem. And if you have shared connections you have an even bigger problem.
But as written, with no significant static fields: no problem.
I thought he was pretty clear on his answer.
Writing my own Provider Class in ASP.NET
"remember that the connection will be shared at the same instance for all users, which can cause bad problems..."
Static classes are difficult to test.
Your question mentions that for a change you'll have to change the class on a couple websites. If your websites were coupled to an interface, then swapping out the implementation would be relatively simple.
In my own projects I avoid public static classes. They can get unwieldy very quickly.
As such no issue it depends how you are using this class, ideally it part of abstract factory pattern to have static connections so that same connection can be used all over application, but having methods such as executereader and other mthods is not a good choice. similarly always check that connection has not been closed or its state before its usage, because if you are having static connection and you used using syntax with executereader then it will close the connection and if some other method used connection after this then it will get the error
The obvious drawbacks are:
hardcoded connection string
without connection pooling in the driver this is very bad: //open conn + //close conn
1) can be ugly solved by using a singleton as the connection string name
2) cannot be solved in a static class without introducing shared data: ie. without planting a knife in your back.
Do you know that the MySQL Connector for .NET now has a MySqlHelper class (you can check it in the source here)?
If you are going to take this route you many want to consider using the Microsoft DAAB SqlHelper v2 offering. It uses the same concept but is much more robust. It also caches SqlParameters. The code came out circa 2001 and has been in constant use by many developers.
http://www.microsoft.com/download/en/details.aspx?id=435
Related
Please, please don't close or mark this question as duplicate, I have already looked StackOverflow and online but couldn't find solution.
Below code works great that I receive data from SQL Server via a stored procedure, then assign to a list of book model and return Json:
public IActionResult GetAllBooks()
{
List<BookViewModel> book = new List<BookViewModel>();
DataTable dataTable = new DataTable();
using (SqlConnection sqlConnection = new SqlConnection(_configuration.GetConnectionString("xxx")))
{
sqlConnection.Open();
SqlDataAdapter sqlData = new SqlDataAdapter("proc_GetBookList", sqlConnection);
sqlData.SelectCommand.CommandType = CommandType.StoredProcedure;
sqlData.Fill(dataTable);
foreach (DataRow dr in dataTable.Rows)
{
book.Add(new BookViewModel
{
Name = dr["Name"].ToString(),
Stock = Convert.ToInt32(dr["Stock"]),
});
}
}
return Json(book);
}
But I am trying to find a better way or best practice e.g serialize or any other techniques so that I don't need to create (View model and Assigning them values) like below. This is small example of only two properties but sometimes I need to map like 20 or more properties, do you guy see any problem in above code? I am new in software development world, any suggestion would be appreciated.
new BookViewModel
{
Name = dr["Name"].ToString(),
Stock = Convert.ToInt32(dr["Stock"]),
};
I have used Newtonsoft JSON (NuGet package) for this purpose.
Example:
using Newtonsoft.JSON;
public string DataTableToJSONWithJSONNet(DataTable table) {
string JSONString = string.Empty;
JSONString = JSONConvert.SerializeObject(table);
return JSONString;
}
You can find this Newtonsoft example and a few other methods here.
Using a query like you are using is pretty much going to make you use this style of assignment. Switching to Entity Framework to query your DB is going be your best bet, since it will do assignment to objects/classes automatically. But I get that doing so after a project is started can be a PITA or nearly impossible (or a very significantly large amount of work) to do. There's also a bit of a learning curve, if you've never used it before.
What you can do to make things easier is to create a constructor for your model that takes in a DataRow and assigns the data on a single place.
public BookViewModel(DataRow dr)
{
Name = dr["Name"].ToString();
Stock = Convert.ToInt32(dr["Stock"]);
}
Then you just call "book.Add(new BookViewModel(dr));" in your foreach loop. This works well if you have to do this in multiple places in your code, so you don't have to repeat the assignments when you import rows.
You might also be able to use Reflection to automatically assign the values for you. This also has a bit of a learning curve, but it can make conversions much simpler, when you have it set up.
Something similar to Reflection is AutoMapper, but that's not as popular as it used to be.
I was going to suggest using a JSON package like Newtonsoft or the built in package for C#, but it looks I got beat to that punchline.
Another option is using Dapper. It's sort of a half-step between your current system and Entity. It can use SQL or it's own query language to cast the results directly to a model. This might be the easiest and most straight forward way to refactor your code.
Dapper and Entity are examples of object relational mappers (ORMs). There are others around you can check out.
I've only listed methods I've actually used and there are many other ways to get the same thing done, even without an ORM. They all have their pros and cons, so do your research to figure out what you're willing to commit to.
Simply just replace your "return Json(book)" with
return Ok(book)
I have been struggling with this bit for over a day now. It appears that many people have asked about similar thing, but they usually want to do something way more advance than what I need. I got an idea what it should look like (I think), but struggle with actually properly implementing it - so here it goes:
I have a form application that does some Odbc, Sql, Csv import/exports.
My main class is the ImportForm class, which contains all the buttons, controls it also creates SQL and ODBC connections in each constructor etc.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ImportForm importForm = new ImportForm();
Application.Run(importForm);
}
.
public partial class ImportForm : Form
public static SqlConnection sqlConnection = new SqlConnection(ConstantValues.SqlConnectionString);
public static OdbcConnection odbcConnection = new OdbcConnection(ConstantValues.OdbcConnectionString);
(...)
I now have few other classes that do different things. For instance once of imports CSV files into SQL Server. It does it through SqlBulk based on the SQL connection defined in the ImportForm class:
internal class CsvImportIntoSql
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
This, however, returns a syntax error 'The name does not exist in the current context'
I tried:
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(importForm.sqlConnection);
But it doesnt work, the class ImportForm is available in the context, but its defined instance importForm is not and I cannot understand why and what I should do to make it work - I have been struggling with that for a while and have to employ different workarounds which often do not make for good code.
Any help would be appreciated.
Almost right: you need the class name ImportForm, not an instance of it ( importForm) to access a static property:
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(ImportForm.sqlConnection);
If the CsvImportIntoSql instance is created in the ImportForm, then your best option would be to inject the sqlConnection, or if it is likely to change after the CsvImportIntoSql instance is created then inject a refrence to the CsvImportIntoSql instance itself.
If I understand, you are trying to use the same sqlConnection variable that is defined in another class. but it appears that you have declared this variable as static, which should help while referring to it from another class:
Try to replace
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
with:
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(ImportForm.sqlConnection);
This should work. however,using the same connection in multiple instance is not always a good practice. instead, you can initialize a new connection for each job.
As we all know solr 4.0 supports atomic updates.
http://wiki.apache.org/solr/UpdateXmlMessages#Optional_attributes_for_.22field.22
Is this supported in solrnet yet?
If yes can I know the syntax.
Thanks a ton.
Thanks to the link you provided, do the following (with obvious changes to match your requirements and assuming you're using some DI container so that your ISolrOperations and ISolrConnection are taken care of via registration of SolrFacility):
private readonly ISolrOperations<Document> _solr;
private readonly ISolrConnection _solrConnection;
public SolrRecordRepository(ISolrOperations<Document> solr, ISolrConnection solrConnection)
{
_solr = solr;
_solrConnection = solrConnection;
}
...
public void UpdateField(int id, string fieldName, int value, bool optimize = false)
{
var updateXml = string.Format("<add><doc><field name='id'>{0}</field><field name='{1}' update='set'>{2}</field></doc></add>", id, fieldName, value);
_solrConnection.Post("/update", updateXml);
_solr.Commit();
if (optimize)
_solr.Optimize();
}
To the best of my knowledge, SolrNet does not yet support atomic updates and I do not see it listed on the SolrNet Project Issues List or any mention in the SolrNet Commits on GitHub.
Please note that the atomic updates are quite limited. If you expect an update feature a-la database - it's not yet there. Under the hood the document is recreated using the stored fields. it can be convenient when you don't want to resend all fields and don't care to store all the fields in the index.
As far as I know, the 'real' update is about to come soon.
I just want an opinion on the proper usage or a proper design with regards to using SqlConnection object. Which of the 2 below is the best use:
A data provider class whose methods (each of them) contain SqlConnection object (and disposed when done). Like:
IList<Employee> GetAllEmployees()
{
using (SqlConnection connection = new SqlConnection(this.connectionString)) {
// Code goes here...
}
}
Employee GetEmployee(int id)
{
using (SqlConnection connection = new SqlConnection(this.connectionString)) {
// Code goes here...
}
}
or
SqlConnection connection; // initialized in constructor
IList<Employee> GetAllEmployees()
{
this.TryOpenConnection(); // tries to open member SqlConnection instance
// Code goes here...
this.CloseConnection();
// return
}
Employee GetEmployee(int id)
{
this.TryOpenConnection(); // tries to open member SqlConnection instance
// Code goes here...
this.CloseConnection();
// return
}
Or is there a better approach than this? I have a focused web crawler type of application and this application will crawl 50 or more websites simultaneously (multithreaded) with each website contained in a crawler object and each crawler object has an instance of a data provider class (above).
The actual database connections will be pooled. As long as all of your SqlConnection instances use the same connection string, they'll all really use the same connection.
I find it cleaner to create the connection instance, use it, then dispose it (in a using block). That way, if the code needs to change to use a different connection string, to use a transaction, or whatever, you have all you need to make the change available right there.
Maybe not really related, but the only time I'd separate any connection object to the class instance level is when I want to create a clear separation of concern to what each method is doing... Perhaps it's too long and need to be refactored into several pieces and each of them need to operate on the same connection as part of a transaction.
I.e.
Create a connection
Start transaction
Call a subroutine to update an order header (passing along the connection or get it from the instance)
Call a subroutine to update all order details (passing along the conneciton or get it from the instance)
End transaction
Close connection
Otherwise, I'd pretty much stick to option 1. W/ connection pooling it's basically won't cost you anything.
I created a C#.net app that uses dates from a SQL Server 2008 database table. Is there a way for me to temporarily store the data so that my program does not have to repeatedly make server calls for the same set of information? I know how to pull the info I need and create a temporary dataset, however, it is only accessible to the particular method or class and then goes away. I need the results to be universally available until the program closes.
This is what I have so far and I am not sure where to go next:
SqlConnection ReportConnect = new SqlConnection(ConnectionString);
String reportQuery = #"SELECT DISTINCT DATE FROM dbo.myTable ORDER BY DATE DESC";
ReportConnect.Open();
SqlCommand cmd = ReportConnect.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = ReportConnect;
cmd.CommandText = reportQuery.ToString();
SqlDataReader rdr = cmd.ExecuteReader();
while(rdr.Read()) {
//I can access the results here
}
//how do I add this data for the life of the program instance to my current
//dataset. Let's say the dataset is named "activeDataset"
If you are going to use key/value pair caching, I recommend you use HttpRuntime.Cache (available outside ASP.NET applications) since it already does alot of work for you.
In it's simplest implementation:
public IList<DateTime> GetUniqueDates()
{
const string CacheKey = "RepositoryName.UniqueDates";
Cache cache = HttpRuntime.Cache;
List<DateTime> result = cache.Get[CacheKey] as List<DateTime>;
if (result == null)
{
// If you're application has multithreaded access to data, you might want to
// put a double lock check in here
using (SqlConnection reportConnect = new SqlConnection(ConnectionString))
{
// ...
result = new List<DateTime>();
while(reader.Read())
{
result.Add((DateTime)reader["Value"]);
}
}
// You can specify various timeout options here
cache.Insert(CacheKey, result);
}
return result;
}
Having said that, I usually use IoC trickery to create a caching layer in front of my repository for the sake of cohesion.
You could create a singleton object, and store the data in this object.
Be aware that there is a lot more to single ton objects that you will have to think about.
Have a look at
Implementing the Singleton Pattern
in C#
Singleton pattern
Implementing Singleton in C#
You should use SQLCacheDependency. Take a look at MSDN
You could store the datatable in a static variable that would be accesible from any part of your code (is this necessary?).
public class MyDataSetCache
{
public static DataSet MyDataSet { get; set; }
}
Some other code...
// SQL Statements....
MyDataSetCache.MyDataSet = activeDataset // Editted to follow OP :-)
I usually serialize whole object to a file and try to read it first before going to database.
You can use a set of implementation hooks to achieve result:
Common data-application layer (data singleton or some data coupling using static class with lesser "visible" methods' dependencies)
Use caching -- you can use Dictionary and common string-keys to detect (ContainsKey method) whether data is already fetched or needs sql-server call. This can be useful when you need different DataSets. Dictionary works pretty fast.
You can definately use Cache to reduce database hits, Besides using SqlDependency you can have a cache based on time. You can invalidate your cache let's say every 4 hours,and hit the database again. Check out Cache.Insert()