How to invoke webservice from sql server 2008? - asp.net

I am working on asp.net(4.0) web application for database i have SQL SERVER 2008. I have created one Web Service, its functionality is to insert data into database. I have deployed my Web Service on the local IIS, in browser its working fine mean it is inserting data in database but my task is to create a procedure that will pass parameters to the Web Service and then Web Service will insert that data. I have tried many thing for this but could complete this task. Any idea that how i can invoke Web Service from SQL SERVER.
I have tried many things like below link and similar techniques that are mention on this URL
http://www.sqlservergeeks.com/forums/microsoft-data-platform/sql-server-bi/9/sql-programming-calling-the-web-service-thru-sql
I have also tried end point but couldn't complete. Even HelloWork method is not getting called from SQL SERVER.
Web Service Name WebService1.asmx
Method public string SaveRecord(string a, string b, string c, string d)
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public string SaveRecord(string userid, string fname, string lname, string email)
{
//here is my code to save records is database
return "";
}

It is possible to call web service from sql server through integration with SQLCLR. Below is code snippet of CLR trigger which received data about deleted records from DB and send it to remote through web service call.
[SqlTrigger(Name = "OnDelete", Target = "Contact1", Event = "FOR DELETE")]
public static void OnDelete()
{
string recid, accountno, address3;
recid = accountno = address3 = string.Empty;
var sqlContext = SqlContext.TriggerContext;
using (var connection = new SqlConnection("context connection=true"))
{
var command = new SqlCommand("SELECT recid, accountno, address3 FROM DELETED; ", connection);
connection.Open();
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
recid = reader[0].ToString();
accountno = reader[1].ToString();
address3 = reader[2].ToString();
}
}
}
if (!string.IsNullOrEmpty(address3))
{
var token = new CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = "organization";
using (var crmService = new CrmService())
{
crmService.Url = "http://domain:5555/MSCRMServices/2007/CrmService.asmx";
crmService.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
crmService.CrmAuthenticationTokenValue = token;
crmService.UnsafeAuthenticatedConnectionSharing = true;
crmService.PreAuthenticate = true;
crmService.Delete(EntityName.contact.ToString(), new Guid(address3));
}
}
}

Related

EPPLUS package works fine locally but returns Internal server error when deployed to azure server

I have my web api that uploads and reads an excel file from the client app and then afterwards saves the data into the database, the application works perfect on locally server but the problem comes when the application is deployed to azure server it returns error 500 internal server error therefore i don't understand why this happens and and don't know how i can track to understand what might be the cause below are my code blocks.
My Interface Class
public interface UploadExcelInterface
{
Task UploadMultipleClients(Client obj);
}
My Service Implementation
public class UploadExcelService : UploadExcelInterface
{
private readonly DbContext _connect;
private readonly IHttpContextAccessor httpContextAccessor;
public UploadExcelService(DbContext _connect, IHttpContextAccessor httpContextAccessor)
{
this._connect = _connect;
this.httpContextAccessor = httpContextAccessor;
}
public async Task UploadMultipleClients(Client obj)
{
var file = httpContextAccessor.HttpContext.Request.Form.Files[0];
if (file != null && file.Length > 0)
{
var folderName = Path.Combine("Datas", "ClientUPloads");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
var fileName = Guid.NewGuid() + ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fullPath = Path.Combine(pathToSave, fileName);
var clientsList = new List<Client>();
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
FileInfo excelFile = new FileInfo(Path.Combine(pathToSave, fileName));
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(excelFile))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
var rowcount = worksheet.Dimension.Rows;
for (int row = 2; row <= rowcount; row++)
{
var Names = (worksheet.Cells[row,2].Value ?? string.Empty).ToString().Trim();
var Address = (worksheet.Cells[row,3].Value ?? string.Empty).ToString().Trim();
var Title = (worksheet.Cells[row,4].Value ?? string.Empty).ToString().Trim();
var Product = (worksheet.Cells[row,5].Value ?? string.Empty).ToString().Trim();
var Order = (worksheet.Cells[row,6].Value ?? string.Empty).ToString().Trim();
var Email = (worksheet.Cells[row,7].Value ?? string.Empty).ToString().Trim();
var Price = (worksheet.Cells[row,8].Value ?? string.Empty).ToString().Trim();
clientsList.Add(new Client
{
Names = Names,
Address = Address,
Title = Title,
Product = Product,
Order = Order,
Email = Email,
Price = Price,
}
}
//adding clients into the database
foreach (Client client in clientsList)
{
var exist = _connect.client.Any(x => x.Email == client.Email);
if (!exist)
{
await _connect.client.AddAsync(client);
}
}
await _connect.SaveChangesAsync();
}
}
}
My Controller Class
[HttpPost]
public async Task UploadMultipleClients([FromForm] Client obj)
{
await uploadExcelInterface.UploadMultipleClients(obj);
}
}
Please any help regarding this error that am getting from the server, and addition on that is it possible to get the data from the excel file without uploading it to server if yes how? because i tried adding the file to memory stream an reading it from memory but it appers not work, any suggestions thanks.
My answer may not help you solve the problem directly, but it can locate the error step by step. After we fix the error, we should be able to solve the problem in this thread.
Suggestions
Please make sure you have inclue EPPlus library in your deploy content.
Enabling ASP.NET Core stdout log (Windows Server)
Azure App Service - Configure Detailed Error Logging
Why
After tested, I am sure azure webapp can support EPPlus. For 500 error, as we don't have a more specific error message to refer to, we can't quickly locate the problem. Following the suggested method, you will surely see some useful information.
E.g:
The class library of EPPlus was not found.
Folders such as Datas are not created.
The database connection string, the test environment and the production environment may be different.
...

ASP.NET Web API - call database to insert via async method, but it doesn't work

I have this method:
public async static Task ExecuteSpAndForget(string sp, Location location, params SqlParameter[] parameters)
{
using (SqlConnection conn = await GetConnectionAsync(location))
{
SqlCommand cmd = new SqlCommand(sp, conn);
cmd.Parameters.AddRange(parameters);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = Int32.Parse(ConfigurationManager.AppSettings["CommandTimeout"]);
await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}
public async static Task<SqlConnection> GetConnectionAsync(Location location)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString" + location]);
await conn.OpenAsync().ConfigureAwait(false);
return conn;
}
And in my log filter I applied to WebApiConfig.cs:
config.Filters.Add(new LogFilter());
And in LogFilter(), I call the database to write log
public static int WriteLog(HttpActionContext actionContext, Exception exception = null)
{
\\logic
var logTask = DatabaseHelper.ExecuteSpAndForget("writelogSP", Location.Log, sqlParams.ToArray());
\\return logic
}
When I am debugging locally, this never writes to the database, when I deployed it to IIS, it sometimes write to the database, sometimes not. I tested it locally in a console app, if I wait several seconds after calling before exit, data can be inserted into the database, otherwise no insert happens if no wait.
Why? How can I use it?
What you are referring to is a background task.
There are different ways of going about it. The simplest one is Task.Run with no await
public static int WriteLog(HttpActionContext actionContext, Exception exception = null)
{
\\logic
// fire and forget, no await
var logTask = Task.Run(async () =>
{
await DatabaseHelper.ExecuteSpAndForget("writelogSP", Location.Log, sqlParams.ToArray());
});
\\return logic;
}
You can check out this link https://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html for a better solution.

Asp.net async db connection not reusing connections

I have a .net mvc / sql server website for a high-traffic application. I'm using async database connections.
Prior to launch I ran a load test, and it blew up pretty quickly under load. The connection pool quickly ran out of connections.
Running sp_who at the database level shows a pile of connections sleeping awaiting command. If I switch to non-async, this does not happen.
So, it appears that new database calls are not using connections sitting in the connection pool, instead they are opening their own new connection. This quickly exhausts the connection pool limit, and begins timing out queries.
The following is the helper I'm using to execute an async datareader. Does anyone see any issue here?
private async Task<List<T>> ExecuteReaderAsync<T>(SqlCommand command, Func<SqlDataReader, T> rowConverter)
{
List<T> ret = new List<T>();
using (SqlConnection connection = new SqlConnection(this.ConnectionString))
{
command.Connection = connection;
await connection.OpenAsync();
using (SqlDataReader reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
ret.Add(rowConverter(reader));
}
reader.Close();
}
connection.Close();
}
return ret;
}
I'm calling the code like the datareader helper like the following:
public async Task<Content> FindContentAsync(int id)
{
Content content = null;
using (SqlCommand command = CreateProcedure("dbo.FindContent"))
{
AddParam(command, "Id", SqlDbType.Int, id);
List<Content> items = await ExecuteReaderAsync<Content>(command, x => BindContent(x));
if (items.Count > 0)
{
content = items[0];
}
}
return content;
}
And calling that from a helper:
public async Task<Content> FindAsync(int id)
{
var db = new DataAccess();
var content = await db.FindContentAsync(id);
return content;
}

Backup of the database in entity framework

i working with entity famework i need to transfer that code
RESTORE DATABASE [showing8-5-2013] FROM DISK = N'C:\Program Files (x86)\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\Backup\Company.bak' WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10
to code Entity frame work
any help thanks
EF is a DB neutral provider concept. Such commands are by their nature DB specific. EF exposes a way to execute an SQL command:
MyContext.Database.ExecuteSqlCommand();
But you may as well just do it directly.
Pass your SQL command into a custom routine eg:
private static bool ExecuteSqlStatement(string connectionString, string statement) {
int rowsAffected;
using (var sqlConnection = new SqlConnection(connectionString)) {
using (var sqlCommand = new SqlCommand(statement, sqlConnection)) {
try {
sqlConnection.Open();
rowsAffected = sqlCommand.ExecuteNonQuery();
}
catch (Exception ex) {
// your handler or re-throw....
return false;
}
}
}
return rowsAffected == -1;
// see http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx
}

C# Windows forms - Data Conduit to connect to a windows form app

Hi guys I need some help with this dataconduit. Its written by my tutor and we used it on a web development project. I am trying to use it for a windows forms application to connect to the database but i get the following error:
An attempt to attach an auto-named database for file C:\Users.... failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
The data conduit works indeed if i use it on a asp.net website but not on a windows forms
i did try to researched but no luck.
I am just testing it with two text box and a save button
thank you
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data;
///This class uses the ado.net sql classes to provide a connection to an sql server database.
///it is free for use by anybody so long as you give credit to the original author i.e me
///Matthew Dean mjdean#dmu.ac.uk De Montfort University 2011
//you will need to modify the name of the namespace to suit your own program.
namespace MyClassLibrary
{
public class clsDataConduit
{
//connection object used to connect to the database
SqlConnection connectionToDB = new SqlConnection();
//data adapter used to transfer data to and from the database
SqlDataAdapter dataChannel = new SqlDataAdapter();
//ado.net class for building the sql commands
SqlCommandBuilder commandBuilder = new SqlCommandBuilder();
//stores a list of all of the sql parameters
List<SqlParameter> SQLParams = new List<SqlParameter>();
//data table used to store the results of the stored procedure
DataTable queryResults = new DataTable();
//data row used to store the data for a new record
DataRow newRecord;
//string variable used to store the connection string
private string connectionString;
public clsDataConduit()
{
//this is the constructor for the class
//you will need to modify this to suit your own database name and folder structure
//
//variable to store the patth to the database
string DbPath;
//variable to store the partial path and file name of your database
//modify this line to suit your own needs
string DatabaseName = "\\MyDatabase\\NamesData.mdf";
//set the DbPath concatenating the name of your database
DbPath = GetParentPath() + DatabaseName;
//build up the connection string for the sql server database
connectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=" + DbPath + ";Integrated Security=True;User Instance=True";
}
private string GetParentPath()
///this function returns the path to the parent folder of the solution
{
//get the folder for the project
string DbPath = System.AppDomain.CurrentDomain.BaseDirectory;
//variable to store the position of the \\ characters
int Posn;
//loop through the path twice
for (int Counter = 0; Counter != 2; Counter++)
{
//find the right most instance of \\
Posn = DbPath.LastIndexOf("\\");
//split the path at that point
DbPath = DbPath.Substring(0, Posn);
//do it one more time
}
//return the new path
return DbPath;
}
public void AddParameter(string ParamName, string ParamValue)
///public method allowing the addition of an sql parameter to the list of parameters
///it accepts two parameters the name of the parameter and its value
{
//create a new instance of the sql parameter object
SqlParameter AParam = new SqlParameter(ParamName, ParamValue);
//add the parameter to the list
SQLParams.Add(AParam);
}
public void Execute(string SProcName)
{
///public method used to execute the named stored procedure
///accepts one parameter which is the name of the stored procedure to use
//open the stored procedure
//initialise the connection to the database
connectionToDB = new SqlConnection(connectionString);
//open the database
connectionToDB.Open();
//initialise the command builder for this connection
SqlCommand dataCommand = new SqlCommand(SProcName, connectionToDB);
//add the parameters to the command builder
//loop through each parameter
for (int Counter = 0; Counter < SQLParams.Count; Counter += 1)
{
//add it to the command builder
dataCommand.Parameters.Add(SQLParams[Counter]);
}
//set the command type as stored procedure
dataCommand.CommandType = CommandType.StoredProcedure;
//initialise the data adapter
dataChannel = new SqlDataAdapter(SProcName, connectionToDB);
//set the select command property for the data adapter
dataChannel.SelectCommand = dataCommand;
//use the copmmand builder to generate the sql insert delete etc
commandBuilder = new SqlCommandBuilder(dataChannel);
//fill the data adapter
dataChannel.Fill(queryResults);
//get the structure of a single record
newRecord = queryResults.NewRow();
//close the connection
connectionToDB.Close();
}
public void WriteToDatabase()
//void method that updates changes to the data adapter thus changing the database
{
//update any changes
dataChannel.Update(queryResults);
}
public DataRow NewRecord
///this method provides access to the new record as a single data row
{
get
{
//return the blank data row
return newRecord;
}
}
public void RemoveRecord(int Index)
//void method that removes a record at a specified index in the query results
{
//remove the record
queryResults.Rows[Index].Delete();
}
public void AddToDataTable()
//void method that adds the new record to the table data
{
//add the new record to the table
queryResults.Rows.Add(newRecord);
//re initialise the new record
newRecord = queryResults.NewRow();
}
public int Count
//property that returns the count of records in the query results
{
get
{
//return the count of the query results
return queryResults.Rows.Count;
}
}
public DataTable QueryResults
//public property that provides access to the query results
{
get
{
//return the query results
return queryResults;
}
set
{
//set the query results
queryResults = value;
}
}
}
}
this is the code for my name class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyClassLibrary
{
public class clsName
{
private string firstName;
private string lastName;
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
}
}
public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
}
}
public void Save()
{
clsDataConduit Names = new clsDataConduit();
Names.Execute("sproc_tblNames_GetAll");
Names.NewRecord["FirstName"] = firstName;
Names.NewRecord["LastName"] = lastName;
Names.AddToDataTable();
Names.WriteToDatabase();
}
}
}
thank you guys but i finally managed to make it work. i am not sure if it is the right way to do it but what u have done is i have commented out the public clsDataConduit() {} method and before this method i have modified the connection string adding the full path of my database as follow: private string connectionString = (#"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users...\NamesData.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True");

Resources