How is it possible to execute a direct SQL command to an ADO.NET connected database?
I want to send a DBCC SHRINKDATABASE to the SQL server, to compress the current datafile after a big deletion process. The function ObjectContext::CreateQuery returns a parser error after the DBCC command. Is there any other way to shrink the database file, or another way to send the SQL command directly to the SQL Server?
I'd just send this as raw SQL:
using (SqlCommand command = new SqlCommand("DBCC SHRINKDATABASE(0)", connection))
{
command.ExecuteNonQuery();
}
Another way is to put the DBCC SHRINKDATABASE in a stored procedure and call the stored procedure from your code.
thanks Mark, I just had to figure out how I can obtain the SqlConnection.
Here is the complete sourcecode (ok could be written a little bit nicer with an extension method):
public ActionResult Optimize()
{
using (BXPartsEntities Entities = new BXPartsEntities())
{
System.Data.EntityClient.EntityConnection eConnection = Entities.Connection as System.Data.EntityClient.EntityConnection;
eConnection.Open();
var SqlConnection = eConnection.StoreConnection as SqlConnection;
if (SqlConnection == null)
throw new ArgumentException("StoreConnection shall be SQL Connection");
using (SqlCommand command = new SqlCommand("DBCC SHRINKDATABASE(0)", SqlConnection))
{
command.ExecuteNonQuery();
}
eConnection.Close();
}
return Content("Done");
}
Related
Below is the code I got from Microsoft page: SqlCommand
public static Int32 ExecuteNonQuery(String connectionString, String commandText, CommandType commandType, params SqlParameter[] parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(commandText, conn))
{
// There're three command types: StoredProcedure, Text, TableDirect. The TableDirect
// type is only for OLE DB.
cmd.CommandType = commandType;
cmd.Parameters.AddRange(parameters);
conn.Open();
return cmd.ExecuteNonQuery();
}
}
}
However, VS code analysis still complains about "CA2100":
Warning CA2100 The query string passed to 'SqlCommand.SqlCommand(string, SqlConnection)' in 'FlexClaimFormRepository.ExecuteNonQuery(string, string, CommandType, params SqlParameter[])' could contain the following variables 'commandText'. If any of these variables could come from user input, consider using a stored procedure or a parameterized SQL query instead of building the query with string concatenations.
I know the exact reason why the warning is there, but anyidea on how to get rid of it? Given setting commandText inside the function is not acceptable since I want it to be a parameter.
I know this question is old, but maybe this will help someone with the same issue. I also was using a stored procedure and therefore suppressed the warning using the information from this article from Microsoft:
https://learn.microsoft.com/en-us/visualstudio/code-quality/in-source-suppression-overview?view=vs-2019 .
Here's the attribute I added to my method:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Security", "CA2100:Review SQL queries for security vulnerabilities", Justification = "Method already uses a Stored Procedure")]
I'm executing same command in every 2 seconds. I think following code creates multiple connections:
[System.Web.Services.WebMethod]
public static int getActivity()
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbconnection"].ToString()))
{
connection.Open();
using (var cmd = new SqlCommand("SELECT TOP 1 ValueX FROM TABLE WHERE ID= 2 AND EVENTID = 2 ORDER BY DATE DESC", connection))
{
var x = cmd.ExecuteScalar();
int Result;
if (x != null)
{
Result = int.Parse(x.ToString());
Console.WriteLine("USER ACTIVITY : " + Result);
}
else
{
Result = -999;
}
connection.Close();
return Result;
}
}
}
If I call this method several time Does following code make multi connection Or single connection ?
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbconnection"].ToString()))
Can someone explain whether I need to modify this code or Is this good one ?
Thanks.
Since you are using the using statement clause so once you are done with the method the resources are freed and the connection is closed. So everytime when you call the same method a new connection will be made. When you are using the using clause then it is equivalent to the below code:
SqlConnection connection = null;
try
{
connection = new SqlConnection(connectionString);
}
finally
{
if(connection != null)
((IDisposable)connection).Dispose();
}
Also note that you dont need to explicitly call the connection.Close(); in your method as using statement will take care of it.
Your method is fine, you just don't need connection.Close() as described by Rahul. Using statement when dealing with SQL objects is good practice.
What you should keep in mind, is that ADO.NET connection pooling, takes care of handling new objects referring to the same connection string, thus minimizing the time needed to open a connection.
More about connection pooling can be found Here
I'm a vb.net guy and have difficulty reading C#. I compiled the C# Dapper to a DLL and use it my app.
My main concern is I think I need to modify the source to integrate by default the Transient Fault Handling Framework for SQL Azure in each SQL query.
I can add the retry logic on the connection level because it is ont top of dapper, but not at the execute query level which is embedded in drapper class.
Anyone has done that yet ?
* UPDATE *
Does using only ReliableSqlConnection on top of Dapper call will handle a retry logic on the execute non query ?
Here is sample code of retry from MS with the transietn fault hanling
using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling;
using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.AzureStorage;
using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure;
using System.Data;
...
using (ReliableSqlConnection conn = new ReliableSqlConnection(connString, retryPolicy))
{
conn.Open();
IDbCommand selectCommand = conn.CreateCommand();
selectCommand.CommandText =
"UPDATE Application SET [DateUpdated] = getdate()";
// Execute the above query using a retry-aware ExecuteCommand method which
// will automatically retry if the query has failed (or connection was
// dropped).
int recordsAffected = conn.ExecuteCommand(selectCommand, retryPolicy);
}
Here is the execute part of Dapper code, same name is used but I guess it is a custom execute function
private static int ExecuteCommand(IDbConnection cnn, IDbTransaction transaction, string sql, Action<IDbCommand, object> paramReader, object obj, int? commandTimeout, CommandType? commandType)
{
IDbCommand cmd = null;
bool wasClosed = cnn.State == ConnectionState.Closed;
try
{
cmd = SetupCommand(cnn, transaction, sql, paramReader, obj, commandTimeout, commandType);
if (wasClosed) cnn.Open();
return cmd.ExecuteNonQuery();
}
finally
{
if (wasClosed) cnn.Close();
if (cmd != null) cmd.Dispose();
}
}
I would recommend wrapping the retry around Dapper, preferably by using the RetryPolicy.ExecuteAction method. That way both the OPEN call to the connection
and the command itself will be retried using the TFH retry policy:
For example:
SqlRetryPolicy.ExecuteAction(() =>
{
// Place Dapper ExecuteCommand here: e.g.
ExecuteCommand(conn, trans, ... )
});
I am trying to use Dapper for our complex queries to remove any lost overhead that was previously existing with NH.
I have the following query (note this has been considerably shrunk):
SELECT DISTINCT *
FROM tasks t
WHERE t.initials = #UserInits
Which is called via our repository as so:
taskRepo.RawExec<TaskListItemDTO>(Query,new {UserInits = "SAS"})
Our implementation of DapperExec consist as follows:
public IEnumerable<T> RawExec<T>(string SQL, object param)
{
return _session.Connection.Query<T>(SQL,param);
}
But Dapper doesn't appear to be adding the parameters to the query, and as a result, we are getting syntax errors.
Incase it helps, we are connecting over ODBC to Informix.
Thanks
Update Code Sample:
Sorry it took so long, been very busy with work! Below is a sample for MS SQL (2008) Server that should simple query the sys.all_objects (systables?) with a param value of 1 or 0 - but in this sample, as ODBC does not use named params, this won't work.
using Dapper;
using DapperSQL;
using System.Collections.Generic;
using System.Data;
using System.Data.Odbc;
namespace DapperTests
{
public class SQLEx
{
private OdbcConnection GetConnection()
{
var cnn = new OdbcConnection("DSN=ODBCSOURCE");
cnn.Open();
// wrap the connection with a profiling connection that tracks timings
return cnn;
}
public IEnumerable<object> DapperTest()
{
using (OdbcConnection conn = GetConnection())
{
return conn.Query("SELECT * FROM sys.all_objects where is_ms_shipped = ?", new { is_ms_shipped = 1 });
}
}
}
I know this is old post, just use SP instead of query, please check this link Dapper using ODBC store procedure Input parm, this using sybase odbc Sp, all odbc use same technique, I wish it works in Informix.
I am first time trying to use filestream to store pdf files on file system using varbinary(MAX) column type of DB.
I have followed following steps.
enabled filestream feature on SQL server 2008 R2.
Create a filegroup for BLOB storage
created table with blob column of type varbinary(max)
Now, I want to use file upload control to select file and when click on upload button it should save the pdf file. Also, how to retrieve the file?
I have tried following code
protected void btnFSupload_Click(object sender, EventArgs e)
{
SqlConnection cn = null;
SqlTransaction tx = null;
SqlCommand cmd = null;
SqlCommand cmd2 = null;
bool bCommit = false;
try
{
// read in the file to be saved as a blob in the database
FileStream input = new FileStream(#"D:\swami.pdf", FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[(int)input.Length];
input.Read(buffer, 0, buffer.Length);
cn = new SqlConnection("server=at-hetal01\\sqlexpress;Initial Catalog=practice;Integrated Security=true;");
cn.Open();
tx = cn.BeginTransaction();
cmd = new SqlCommand("dbo.stp_AddBLOB", cn, tx);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataReader r = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow);
r.Read();
string id = r[0].ToString();
string path = r[1].ToString();
r.Close();
// get the transaction context
cmd2 = new SqlCommand("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()", cn, tx);
Object obj = cmd2.ExecuteScalar();
byte[] txCtx = (byte[])obj;
// open the filestream to the blob
SafeFileHandle handle = OpenSqlFilestream(path,DESIRED_ACCESS_WRITE,SQL_FILESTREAM_OPEN_NO_FLAGS,txCtx,(UInt32)txCtx.Length,0);
// open a Filestream to write the blob
FileStream output = new FileStream(handle,FileAccess.Write,buffer.Length,false);
output.Write(buffer,0,buffer.Length);
output.Close();
if (handle != null && !handle.IsClosed)
handle.Close();
bCommit = true;
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
finally
{
if (cn != null)
{
switch (bCommit)
{
case true:
tx.Commit();
break;
case false:
tx.Rollback();
break;
}
cn.Close();
}
}
}
Above code shows error as below
The operating system returned the error '0xc000003a({Path Not Found} The path %hs does not exist.)' while attempting 'NtCreateFile' on 'D:\DB\FS\d11132f8-c2a8-452d-ae0c-208164a550d7\beb8e1f1-8116-440b-870b-7cef4281a15d\0000001c-000000e4-010d'. The statement has been terminated.
So, any clue on this?
If you have altered your table using SSMS table designer, the FILESTEAM column attribute will be lost producing the path not found. Make sure the FILESTREAM attribute is set for the file field by running the follwoing statement in your database:
select SERVERPROPERTY('FilestreamShareName') as ShareName,
SERVERPROPERTY('FilestreamConfiguredLevel') as ConfiguredLevel,
SERVERPROPERTY('FilestreamEffectiveLevel') as EffectiveLevel
You'll need to alter the table via a script and NOT SSMS to tie your varchar(max)/filestream field to the FileGroup you should have already created.
When I ran into this issue, I found the answer on StackOverflow, but can't seem to find it again for the reference.
I know this is old, but for future reference:
We checked the SERVERPROPERTY values that #BMP suggested. They were configured correctly, so that didn't help.
However, we went ahead and turned OFF the windows file share part of the file streaming access. Once this was done, the error went away.
In our case it was a web app running on the exact same machine as the sql server which exhibited the problem. I'm not sure if the web app's app pool user didn't have access to the file share created by windows or not.
The details were:
Windows 2003 Server (x86)
IIS 6
SQL Server 2008 R2 Express
UPDATE: Apparently this worked for a few days. It's not working any more.