how to enable SQL Application Role via Entity Framework - sql

I'm now developing big government application with entity framework. at first i have one problem about enable SQL application role. with ado.net I'm using below code:
SqlCommand cmd = new SqlCommand("sys.sp_setapprole");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = _sqlConn;
SqlParameter paramAppRoleName = new SqlParameter();
paramAppRoleName.Direction = ParameterDirection.Input;
paramAppRoleName.ParameterName = "#rolename";
paramAppRoleName.Value = "AppRole";
cmd.Parameters.Add(paramAppRoleName);
SqlParameter paramAppRolePwd = new SqlParameter();
paramAppRolePwd.Direction = ParameterDirection.Input;
paramAppRolePwd.ParameterName = "#password";
paramAppRolePwd.Value = "123456";
cmd.Parameters.Add(paramAppRolePwd);
SqlParameter paramCreateCookie = new SqlParameter();
paramCreateCookie.Direction = ParameterDirection.Input;
paramCreateCookie.ParameterName = "#fCreateCookie";
paramCreateCookie.DbType = DbType.Boolean;
paramCreateCookie.Value = 1;
cmd.Parameters.Add(paramCreateCookie);
SqlParameter paramEncrypt = new SqlParameter();
paramEncrypt.Direction = ParameterDirection.Input;
paramEncrypt.ParameterName = "#encrypt";
paramEncrypt.Value = "none";
cmd.Parameters.Add(paramEncrypt);
SqlParameter paramEnableCookie = new SqlParameter();
paramEnableCookie.ParameterName = "#cookie";
paramEnableCookie.DbType = DbType.Binary;
paramEnableCookie.Direction = ParameterDirection.Output;
paramEnableCookie.Size = 1000;
cmd.Parameters.Add(paramEnableCookie);
try
{
cmd.ExecuteNonQuery();
SqlParameter outVal = cmd.Parameters["#cookie"];
// Store the enabled cookie so that approle can be disabled with the cookie.
_appRoleEnableCookie = (byte[]) outVal.Value;
}
catch (Exception ex)
{
result = false;
msg = "Could not execute enable approle proc." + Environment.NewLine + ex.Message;
}
But no matter how much I searched I could not find a way to implement on EF.
Another question is: how to Add Application Role to Entity data model designer?
I'm using the below code for execute parameter with EF:
AEntities ar = new AEntities();
DbConnection con = ar.Connection;
con.Open();
msg = "";
bool result = true;
DbCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
var d = new DbParameter[]{
new SqlParameter{ ParameterName="#r", Value ="AppRole",Direction = ParameterDirection.Input}
, new SqlParameter{ ParameterName="#p", Value ="123456",Direction = ParameterDirection.Input}
};
string sql = "EXEC " + procName + " #rolename=#r,#password=#p";
var s = ar.ExecuteStoreCommand(sql, d);
When run ExecuteStoreCommand this line return error:
Application roles can only be activated at the ad hoc level.

I do it the following way (assuming Database First):
I create the DbContext from the db and call it MyEntitiesBase
I inherit from MyEntitiesBase to create MyEntities with the following code:
public partial class MyEntities : MyEntitiesBase
{
private byte[] appRoleCookie;
private void SetAppRole()
{
try
{
appRoleCookie = Database.SqlQuery<byte[]>(
#"
DECLARE #cookie VARBINARY(8000)
DECLARE #r INT
EXEC sp_setapprole 'user', 'pass', #fCreateCookie = true, #cookie = #cookie OUTPUT
SELECT #cookie").First();
}
catch
{
throw new AuthenticationException();
}
}
private void UnSetAppRole()
{
bool failed = Database.SqlQuery<bool>("DECLARE #result BIT; EXEC #result = sp_unsetapprole #cookie = " + appRoleCookie.ToHexadecimalString() + "; SELECT #result").First();
if (failed)
throw new SecurityException();
}
public MyEntities() : base()
{
Database.Connection.Open();
SetAppRole();
}
private bool disposed = false;
protected override void Dispose(bool disposing)
{
if (disposed)
return;
UnSetAppRole();
Database.Connection.Close();
disposed = true;
base.Dispose(disposing);
}
}
Where ToHexadecimalString is an extension method for IEnumerable<byte>, as follows:
public static class BytesExtensions
{
public static string ToHexadecimalString(this IEnumerable<byte> bytes)
{
return "0x" + string.Concat(bytes.Select(b => b.ToString("X2")));
}
}
And that's it. Works with connection pooling on and everything. You just use this inherited version instead of the one generated by EF.

Basically what you are doing is calling a stored procedure.
Entity Framework has functionality to excute stored procedures. Here is an explaination with a video: http://msdn.microsoft.com/en-us/data/gg699321.aspx
If your scrol down to the section "Using Import Functions to Map Stored Procedures" you will find the part that is relevant for you.

Related

How Can I call Store procedure and a table in the same function in .net core repository?

I am making an API using ASP.netCore to fetch data from teradata. I have 2 store procedure on Teradata DB one for encryption one for description. What I want to achieve is when user call the get method to fetch data, my Store procedure should run first and then it should return all table to user(changed as SP).
I have tried a lot but didn't manage to find any way to call store procedure and Select * table together. If I run the only store procedure OR call only select * table it work. I want to call both (SP and select*) so first SP should run and change the data then return the changed data table.
My codes are following.
Codes for GetDataTable
public IEnumerable<myTable> GetData(IConfiguration _configuration)
{
try
{
myTable TableReturn = new myTable();
List<myTable> dataReturn = new List<myTable>();
var connectionString = _configuration.GetConnectionString("TeradataConnectionString");
using (var connection = new TdConnection(connectionString))
{
'Date_Of_Birth', ENCRYPTEDSTRING);";
TdCommand cmd = new TdCommand("SELECT * FROM Project.myTable;", connection) ;
TdCommand Db = (TdCommand)cmd;
Db.Connection = connection;
connection.Open();
TdDataReader reader = Db.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
var newTable = new myTable();
newTable.Employee_Id = (string)reader.GetString(0);
newTable.First_name = (string)reader.GetString(1);
newTable.Last_Name = (string)reader.GetString(2);
newTable.Date_Of_Birth = (string)reader.GetString(3);
newTable.Phone = (string)reader.GetString(4);
newTable.Em_Position = (string)reader.GetString(5);
dataReturn.Add(newTable);
}
}
else
{
Console.WriteLine("no rows found");
}
}
return dataReturn;
}
catch (Exception e)
{
throw new Exception();
}
}
My codes for store procedure are following
public IEnumerable<DecryptedData> DecryptedData(IConfiguration _configuration)
{
// DecryptedData DecryptedReturn = new DecryptedData();
List<DecryptedData> dataReturn = new List<DecryptedData>();
var connectionString = _configuration.GetConnectionString("TeradataConnectionString");
using (var connection = new TdConnection(connectionString))
{
string command = "CALL Project.Decryption(STATUS,'Project' ,'myTable', 'Date_Of_Birth', ENCRYPTEDSTRING);";
TdCommand cmd = new TdCommand(command, connection);
TdCommand Db = (TdCommand)cmd;
Db.Connection = connection;
connection.Open();
TdDataReader reader = Db.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
var DecryptedData = new DecryptedData();
DecryptedData.Date_Of_Birth = reader.GetString(1);
dataReturn.Add(DecryptedData);
Console.WriteLine(dataReturn);
}
}
else
{
Console.WriteLine("no rows found");
}
}
return dataReturn;
}

Can't use retrieved data from one query into another one?

I need to use a variable (edifcodigo) which assigned value is retrieved from one query to insert it in a table by using other query but there is a error that says this variable is not available in actual context. I'm kind of new in aspnet, could anybody know how to figure this out?
This is the code I have:
//Connect to db
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
//find building code by querying the database
try
{
using (SqlConnection conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (SqlCommand query = new SqlCommand(sql, conexion))
{
SqlDataReader result = query.ExecuteReader();
while (result.Read())
{
string edifcodigo = result["codigo"].ToString();
}
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
//Save referer friend
try
{
using (SqlConnection conn = new SqlConnection(connetionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
That's because you declared the variable inside a different code block. Every time you open a curly bracket, you open a new code block. Every time you close the curly bracket, you close the current code block. Each code block have it's own scope - it can access variables declared in the surrounding code block, but not variables declared in "sibling" code blocks.
Also, please read about parameterized queries and how they protect you from SQL injection, and change your queries accordingly.
Also, you don't need to close the connection between the two commands, and you can reuse a single command instance in this case. Here is an improved version of your code:
//Connect to db
var connetionString = #"myconexionstring";
var sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto = #nombre_proyecto";
//find building code by querying the database
try
{
using (var conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (var cmd = new SqlCommand(sql, conexion))
{
cmd.Parameters.Add("#nombre_proyecto", SqlDbType.NVarChar).Value = uedif;
var edifcodigo = cmd.ExecuteScalar();
//Save referer friend
cmd.Parameters.Clear();
cmd.CommandText = "DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
You are declaring the string variable inside your while loop, it loses scope once you exit the while loop, move it's declaration above with:
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
string edifcodigo = "";
You are trying to use a variable that declared in another scope. edifcodigo should be declared in the parent scope of both try blocks.
//Connect to db
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
string edifcodigo=""; // YOU SHOULD DECLARE edifcodigo HERE
and than rest of code will come
//find building code by querying the database
try
{
using (SqlConnection conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (SqlCommand query = new SqlCommand(sql, conexion))
{
SqlDataReader result = query.ExecuteReader();
while (result.Read())
{
edifcodigo = result["codigo"].ToString();
}
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
//Save referrer friend
try
{
using (SqlConnection conn = new SqlConnection(connetionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}

MVC 5 Convert SQL Query to EF Linq

I have this result:
The problem is that I am not using the power of EF.
I followed this EF tutorial but i'm now able to do it.
ActivityLogController.cs
using System;
...
namespace AccountSystem.Controllers
{
public class ActivityLogController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: ActivityLog
public ActionResult Index()
{
/* var id = User.Identity.GetUserId();
var Emaill = (from x in db.Users
where x.Id == id
select x.Email).Single(); */
//string Access = AccessQ.ToString();
IEnumerable<ActivityLogViewData> model = null;
List<ActivityLogViewData> verify = new List<ActivityLogViewData>();
SqlConnection connection = new SqlConnection("xxx");
connection.Open();
SqlCommand command = new SqlCommand("", connection);
command.CommandText = "select dbo.AspNetUsers.Email,dbo.AspNetUsers.UserName,dbo.ActivityLogModels.ID,dbo.ActivityLogModels.Acess,dbo.AspNetUsers.Id from dbo.ActivityLogModels inner join dbo.AspNetUsers on dbo.ActivityLogModels.userID=dbo.AspNetUsers.Id";
SqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
verify.Add(new ActivityLogViewData { Email = dr[0].ToString(), UserName = dr[1].ToString(), accessID = Convert.ToInt32(dr[2].ToString()), Acess = Convert.ToDateTime(dr[3].ToString()), userID = dr[4].ToString()});
}
connection.Close();
//verify.Add(new ActivityLogViewData {Email = Emaill });
//return View(db.ActivityLog.ToList());
return View(verify);
}
The commented lines are my unsuccessful tries.
Can someone convert this to use EF?
TiA!

Loading data from SQL Server into C# application

I have some problem accessing my data from a SQL Server database via C# application. I have a small project to make and I can't go further because my data is loading in. I try to load it in a DataGridView.
Here are some code examples:
public List<Country> GetCountryList()
{
string query = "SELECT * FROM Orszag", error = string.Empty;
SqlDataReader rdr = ExecuteReader(query, ref error);
List<Country> countryList = new List<Country>();
if (error == "OK")
{
while (rdr.Read())
{
Country item = new Country();
item.CountryId = Convert.ToInt32(rdr[0]);
item.CountryName = rdr[1].ToString();
countryList.Add(item);
}
}
CloseDataReader(rdr);
return countryList;
}
This is where I put my data in a list
private void FillDgvGames()
{
dgvGames.Rows.Clear();
List<Country> CountryList = m_Country.GetCountryList();
foreach (Country item in CountryList)
{
dgvGames.Rows.Add(item.CountryId,item.CountryName);
}
}
And this is where I retrieve it ... I have to make the same thing with 8 more tables but this is the simplest and I thought it's easier this way.... if someone can help me I'd appreciate it ...
PS:
This is the execute reader
protected SqlDataReader ExecuteReader(string query, ref string errorMessage)
{
try
{
OpenConnection();
SqlCommand cmd = new SqlCommand(query, m_Connection);
SqlDataReader rdr = cmd.ExecuteReader();
errorMessage = "OK";
return rdr;
}
catch (SqlException e)
{
errorMessage = e.Message;
CloseConnection();
return null;
}
}
And this is the connection string
protected string m_ConnectionString = "Data Source=SpD-PC;Initial Catalog=master;Integrated Security=SSPI";
Are you setting the data source of your DataGridView?
dgvGames.DataSource = CountryList;

WCF Service Issues with Java Client

This is an interesting problem, and I will do my best to explain. If you have any questions, please ask.
I have written a WCF service that is suppose to communicate with a JAVA client. This service was created via contract first from a WSDL. Now, according to the WCF test client everything works, even testing on a PHP client works as well. But when it comes to the Java client, the request messages and subsequent response messages fail to return: I get a null object SOAP fault. Here is were I think the problem lies:
According to the XSD and WSDL, I have a DateTime value that I am suppose to take in. This dateTime value from the client is of form: 2012-01-01T12:00:00.00Z. Unfortunately, this input is not valid with the built in .NET datetime. So, to get around this, I changed my code to take in a string datatype, convert that string to a Datetime to send it to the database, get a response from the database in that dateTime and convert it back to a string for the response to return a value that is like the one that was inputted.
I built a logger to check to see if the messages were being sent to and from my wcf service. From that, I have identified that messages from the client were not being received. My only guess is that it is because of the datetime issue.
Is there a way to take in a dateTime datatype in the format: 2012-01-01T12:00:00.000Z? If i can, then that will mean that the request will match my datatype and maybe it will work.
Here is some code:
public partial class findSeatsRequest
{
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineData", Order=0, Name="departAirport")]
public string DepartAirport;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineData", Order=1, Name="arriveAirport")]
public string ArriveAirport;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=2, Name="earliestDepartTime")]
public string EarliestDepartTime;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=3, Name="latestDepartTime")]
public string LatestDepartTime;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=4, Name="minimumSeatsAvailable")]
public int MinimumSeatsAvailable;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=5, Name="maximumFlightsToReturn")]
public int MaximumFlightsToReturn;
public findSeatsRequest()
{
}
public findSeatsRequest(string departAirport, string arriveAirport, string earliestDepartTime, string latestDepartTime, int minimumSeatsAvailable, int maximumFlightsToReturn)
{
this.DepartAirport = departAirport;
this.ArriveAirport = arriveAirport;
this.EarliestDepartTime = earliestDepartTime;
this.LatestDepartTime = latestDepartTime;
this.MinimumSeatsAvailable = minimumSeatsAvailable;
this.MaximumFlightsToReturn = maximumFlightsToReturn;
}
}
public partial class findSeatsResponse
{
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineData", Order=0, Name="flight")]
[XmlElementAttribute("flight")]
public System.Collections.Generic.List<flightType> Flight;
public findSeatsResponse()
{
}
public findSeatsResponse(System.Collections.Generic.List<flightType> flight)
{
this.Flight = flight;
}
}
public virtual findSeatsResponse findSeats(findSeatsRequest request)
{
string departAirport = request.DepartAirport;
string arriveAirport = request.ArriveAirport;
string earliestDepartTime = request.EarliestDepartTime;
string latestDepartTime = request.LatestDepartTime;
int minimumSeatsAvailable = request.MinimumSeatsAvailable;
int maximumFlightsToReturn = request.MaximumFlightsToReturn;
SqlCommand cmd = null;
DataSet ds = new DataSet();
List<flightType> flight = new List<flightType>();
EventLogger log = new EventLogger();
findSeatsRequest inValue = new findSeatsRequest();
inValue.DepartAirport = departAirport;
inValue.ArriveAirport = arriveAirport;
inValue.EarliestDepartTime = earliestDepartTime;
inValue.LatestDepartTime = latestDepartTime;
inValue.MinimumSeatsAvailable = minimumSeatsAvailable;
inValue.MaximumFlightsToReturn = maximumFlightsToReturn;
string latestT = inValue.LatestDepartTime.Replace("T", " ");
string latestZ = latestT.Replace("Z", "");
DateTime _latestDepartTime = DateTime.ParseExact(latestZ, "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
string earliestT = inValue.EarliestDepartTime.Replace("T", " ");
string earliestZ = earliestT.Replace("Z", "");
DateTime _earliestDepartTime = DateTime.ParseExact(earliestZ, "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
log.WriteToDataBase(DateTime.Now, "FindSeats", 1, "This is the request: " + inValue);
//Check Maximum Flights
if (inValue.MaximumFlightsToReturn > 100 | inValue.MaximumFlightsToReturn < 0)
{
throw new FaultException(
"You cannot select more than 100 flights to return, or the maximum flights to return is negative.",
new FaultCode("OutOfRange"));
}
// Check Minimum Seats Available.
if (inValue.MinimumSeatsAvailable < 0)
{
throw new FaultException(
"You minimum seats available cannot be negative.",
new FaultCode("OutOfRange"));
}
// Check for valid Departure Airport
if (departAirport != null && departAirport != "ANY")
{
try
{
string strConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
string check = "SELECT DepartAirport FROM Flight WHERE DepartAirport='" + departAirport + "'";
cmd = new SqlCommand(check, conn);
cmd.CommandText = check;
SqlDataReader depAirport;
depAirport = cmd.ExecuteReader();
if (depAirport.HasRows == false)
{
throw new FaultException(
"Invalid Airport code used.",
new FaultCode("Invalid Text Entry"));
}
}
finally
{
if (cmd != null)
cmd.Dispose();
}
}
// Check for valid Arrival Airport
if (arriveAirport != null && arriveAirport != "ANY")
{
try
{
string strConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
string check = "SELECT ArriveAirport FROM Flight WHERE ArriveAirport='" + arriveAirport + "'";
cmd = new SqlCommand(check, conn);
cmd.CommandText = check;
SqlDataReader arrAirport;
arrAirport = cmd.ExecuteReader();
if (arrAirport.HasRows == false)
{
throw new FaultException(
"Invalid Airport code used.",
new FaultCode("Invalid Text Entry"));
}
}
finally
{
if (cmd != null)
cmd.Dispose();
}
}
try
{
string strConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
cmd = new SqlCommand("usp_NewFindSeats", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#DepartureAirport", inValue.DepartAirport));
cmd.Parameters.Add(new SqlParameter("#ArrivalAirport", inValue.ArriveAirport));
cmd.Parameters.Add(new SqlParameter("#EarliestDepTime", _earliestDepartTime));
cmd.Parameters.Add(new SqlParameter("#LatestDepTime", _latestDepartTime));
cmd.Parameters.Add(new SqlParameter("#minSeatsAvailable", inValue.MinimumSeatsAvailable));
cmd.Parameters.Add(new SqlParameter("#maxFlightsRequested", inValue.MaximumFlightsToReturn));
using (SqlDataReader sqlReader = cmd.ExecuteReader())
{
while (sqlReader.Read())
{
flightType Flight = new flightType();
Flight.FlightId = sqlReader.GetString(0);
Flight.DepartAirport = sqlReader.GetString(1);
Flight.ArriveAirport = sqlReader.GetString(2);
Flight.DepartTime = sqlReader.GetDateTime(3).ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
Flight.ArriveTime = sqlReader.GetDateTime(4).ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
Flight.FlightSeatsAvailable = sqlReader.GetInt32(5);
Flight.FlightSeatPriceUSD = sqlReader.GetDouble(6);
flight.Add(Flight);
}
}
For this particular problem, the issue wasn't anything I thought it was in the beginning. Firstly, had to use WrapperNames in my C# code's request operations and the names I used were incorrect.
Secondly, I needed to specify SOAP Body encoding which I had to do within my Interface layer.
[XmlSerializerFormatAttribute(SupportFaults=true, Style=OperationFormatStyle.Document ,Use=OperationFormatUse.Literal)]