Procedure (modified):
alter procedure searchProgramUnitResult(
#id char(10)
)
as
begin
select id from table1 where id = #id
end
Sam procedure in the DBML Designer (after importing the procedure to the MVC project):
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.searchProgramUnit")]
public ISingleResult<searchProgramUnitResult> searchProgramUnit([global::System.Data.Linq.Mapping.ParameterAttribute(DbType="VarChar(10)")] ref string id){
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())),id);
id = ((string)(result.GetParameterValue(0)));
return ((ISingleResult<searchProgramUnitResult>)(result.ReturnValue));
}
Question is, how do I retrieve the result set in another C# class?
public ??Data-type search (string id){
DataContextClass db = new DataContextClass();
??Datatype results = db.searchProgramUnit(id);
return results;
}
If you have mapped the stored procedure in your DbContext you can call it like that:
using (var context = new DataContextClass())
{
var courses = context.searchProgramUnit("1");
foreach (table1 cs in table1s)
Console.WriteLine(cs.Name);
}
another approach which works also with Code First:
using (var ctx = new DataContextClass())
{
var idParam = new SqlParameter
{
ParameterName = "id",
Value = "1"
};
var table1List = ctx.Database.SqlQuery<table1>("exec searchProgramUnitResult #id ", idParam).ToList<table1>();
foreach (table cs in table1List)
Console.WriteLine("Name: {0}", cs.Name);
}
table1 is your entity/class name!
Are you asking about the data type?
public List<string> search (string id){
DataContextClass db = new DataContextClass();
List<string> results = db.searchProgramUnit(id).ToList();
return results;
}
Related
I am attempting to add the variable newRetentionLimit to a table in Microsoft SQL Server. I pass the value I want to insert into a parameter and then run ExecuteNonQuery. I get no errors back but the newRetentionLimit isn't placed into the table. I have debugged to make sure that newRetentionLimit isn't null and is an actual integer.
The problem appears to be that ExecuteNonQuery isn't retrieving the parameter value based on the name I put in the script. It appears its just trying to run the script with the parameter name. Anyone have any idea why?
if (request.SystemSettings.Any(s => s.SettingName.Equals("HISTORYRETENTIONDAYS")))
{
var entities = entityRepo.GetList();
var newRetentionLimit = request.SystemSettings.Find(setting => setting.SettingName.Equals("HISTORYRETENTIONDAYS")).SettingValue.ToInt();
var requestContext = new RequestContext();
var sqlParameter = new List<SqlParameter> {
SqlParameterMaker.MakeTypedValueParameter("#retentionValue",newRetentionLimit, SqlDbType.Int)
};
foreach (var entity in entities)
{
var sql = $#"ALTER TABLE [data].[t{entity.Name}] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [hist].[t{entity.Name}], HISTORY_RETENTION_PERIOD = #retentionValue DAYS));";
requestContext.DatabaseContext.ExecuteNonQuery(sql, sqlParameter);
}
}
I ended up finding a solution that still allows me to maintain the use of SqlParameter
if (request.SystemSettings.Any(s => s.SettingName.Equals("HISTORYRETENTIONDAYS")))
{
var entities = entityRepo.GetList();
var newRetentionLimit = request.SystemSettings.Find(setting => setting.SettingName.Equals("HISTORYRETENTIONDAYS")).SettingValue.ToInt();
var requestContext = new RequestContext();
foreach (var entity in entities)
{
var sqlParameters = new List<SqlParameter>{
new SqlParameter("#entityName", entity.Name),
new SqlParameter("#retentionPeriod", newRetentionLimit)
};
var sql = "EXEC('ALTER TABLE [data].[t' + #entityName + '] SET (SYSTEM_VERSIONING = ON (HISTORY_RETENTION_PERIOD = ' + #retentionPeriod + ' DAYS))');";
requestContext.DatabaseContext.ExecuteNonQuery(sql, sqlParameters.ToArray());
}
}
I have different input parameters to enter and all those parameters need to enter in different tables. Therefore I use 3 different stored procedures. From each stored procedure, i need to use the output parameter of the former stored procedure as an input parameter.
Those are the 3 stored procedures that I use
Stored procedure 1 = Levlotnr:
create procedure Levlotnr
(#lotleverancier nvarchar (256),
#leverancier nvarchar (256),
#newinsertedlevID int output)
as
insert into leveranciersLotnr
values (#lotleverancier,
(select leveranciersID
from Leverancier
where LeveranciersNaam = #leverancier) )
select ##IDENTITY as newinsertedlevID
Stored procedure 2 = LotIN:
create procedure LotIN
(#datumIN datetime,
#hoeveelIN decimal,
#grondstofIN nvarchar(256),
#newinsertedLotnrINID int output,
#lotnlevID int)
as
insert into LotnummerIN
values (#datumIN, #hoeveelIN,
(select GrondstofID
from Grondstoffen
where Grondstofomschrijving = #grondstofIN),
#lotnlevID)
select ##IDENTITY as newinsertedLotnrIN
Stored procedure 3 = StockIN:
create procedure StockIN
(#omschrstockIN nvarchar (256),
#lotnrIN int)
as
update StockPlaatsIN
set LotnummerINID = #lotnrIN
where StockINOmschrijving = #omschrstockIN
And this is a code that I already wrote
public void Nieuweontvangst (DateTime datumIN, string leverancier,
string levlotnr, double hoeveelheidIN,
string eenheidIN, string grondstofIN,
string stockplaatsIN, int lotnrlevID, int lotnrINID)
{
var manager = new LotnummersDBManager();
using (var conLotnummers = manager.Getconnection())
{
conLotnummers.Open();
using (var traNieuweOntvangst =
conLotnummers.BeginTransaction(IsolationLevel.ReadCommitted))
{//begin traNieuweOntvangst
//first transaction: the output parameter #newinsertedlevID
//just needs to be used in the second transaction, but not be displayed
//------------------
using (var comlevlotnrs = conLotnummers.CreateCommand())
{
comlevlotnrs.Transaction = traNieuweOntvangst;
comlevlotnrs.CommandType = CommandType.StoredProcedure;
comlevlotnrs.CommandText = "Levlotnr"; //name of first
stored procedure
var parlotleverancier = comlevlotnrs.CreateParameter();
parlotleverancier.ParameterName = "#Lotleverancier";
parlotleverancier.Value = levlotnr;
comlevlotnrs.Parameters.Add(parlotleverancier);
var parleverancier = comlevlotnrs.CreateParameter();
parleverancier.ParameterName = "#leverancier";
parleverancier.Value = leverancier;
comlevlotnrs.Parameters.Add(parleverancier);
var parlotlevID = comlevlotnrs.CreateParameter();
parlotlevID.ParameterName = "#newinsertedlevID";
parlotlevID.DbType = DbType.Int32;
parlotlevID.Direction = ParameterDirection.Output;
comlevlotnrs.Parameters.Add(parlotlevID);
}
using (var comLotnrsIN = conLotnummers.CreateCommand())
{// second transaction= output parameter #newinsertedlevID
// should be used here where now stands #lotnrlevIN.
// THIS IS WHERE I STRUGGLE
// also here I get an output parameter
// #newinsertedLotnrINID only to be used in the 3rd
// transaction, not to be displayed.
comLotnrsIN.Transaction = traNieuweOntvangst;
comLotnrsIN.CommandType = CommandType.StoredProcedure;
comLotnrsIN.CommandText = "LotnrIN";
var pardatumIN = comLotnrsIN.CreateParameter();
pardatumIN.ParameterName = "#datumIN";
pardatumIN.Value = datumIN;
comLotnrsIN.Parameters.Add(pardatumIN);
var parhoeveelIN = comLotnrsIN.CreateParameter();
parhoeveelIN.ParameterName = "#hoeveelIN";
parhoeveelIN.Value = hoeveelheidIN;
comLotnrsIN.Parameters.Add(parhoeveelIN);
var pargrondstofIN = comLotnrsIN.CreateParameter();
pargrondstofIN.ParameterName = "#grondstofIN";
pargrondstofIN.Value = grondstofIN;
comLotnrsIN.Parameters.Add(pargrondstofIN);
var parlotnrlevIN = comLotnrsIN.CreateParameter();
parlotnrlevIN.ParameterName = "#lotnrlevIN";
parlotnrlevIN.Value = lotnrlevID;
comLotnrsIN.Parameters.Add(parlotnrlevIN);
var parLotIN = comLotnrsIN.CreateParameter();
parLotIN.ParameterName = "#newinsertedLotnrINID";
parLotIN.DbType = DbType.Int32;
parLotIN.Direction = ParameterDirection.Output;
comLotnrsIN.Parameters.Add(parLotIN);
}
using (var comStockeren = conLotnummers.CreateCommand())
{
//Third transaction
// I need to use the output parameter from 2nd transaction
// #newinsertedLotnrINID where you see now #lotnrINID.
//THIS IS THE SAME STRUGGLE AS 2ND TRANSACTION
comStockeren.Transaction = traNieuweOntvangst;
comStockeren.CommandType = CommandType.StoredProcedure;
comStockeren.CommandText = "StockIN";
var parlotIN = comStockeren.CreateParameter();
parlotIN.ParameterName = "#lotnrINID";
parlotIN.Value = lotnrINID;
var paromschrStockIN = comStockeren.CreateParameter();
paromschrStockIN.ParameterName = "#omschrstockIN";
paromschrStockIN.Value = stockplaatsIN;
comStockeren.Parameters.Add(paromschrStockIN);
}
traNieuweOntvangst.Commit();
}
}
}
I'm using ORM in my project. Currently seed data is taken from sql scripts but I would like to create seed data basing on my c# code. For example, I have sql:
SET IDENTITY_INSERT [dbo].[State] ON
INSERT INTO [dbo].[State] ([Id], [Code], [Name]) VALUES (1, N'AL', N'Alabama')
INSERT INTO [dbo].[State] ([Id], [Code], [Name]) VALUES (2, N'AK', N'Alaska')
SET IDENTITY_INSERT [dbo].[State] OFF
And instead of it I want to have a string:
new List<State>
{
new State { Id = 1, Code = "AL", Name = "Alabama" },
new State { Id = 2, Code = "AK", Name = "Alaska" }
};
How can I achieve it?
For INSERT statements (as you said you need seed) you can create helper method like this:
public static List<State> ParseSqlScript(string sqlScriptPath)
{
using (var reader = new StreamReader(sqlScriptPath))
{
var sqlScript = reader.ReadToEnd();
var pattern = #"INSERT INTO \[dbo\].\[State\] \(\[Id\], \[Code\], \[Name\]\) VALUES (\(.*?\))";
var regex = new Regex(pattern);
var matches = regex.Matches(sqlScript);
var states = new List<State>();
foreach (Match match in matches)
{
var values = match.Groups[1].Value.Split(new [] { '(', ',',' ',')' }, StringSplitOptions.RemoveEmptyEntries);
var id = int.Parse(values[0]);
var code = values[1].Substring(2, values[1].Length - 3);
var name = values[2].Substring(2, values[2].Length - 3);
foreach (var value in values)
{
var state = new State() { Id = id, Code = code, Name = name };
states.Add(state);
}
}
return states;
}
}
If you also need other CRUD statements you will probably need to get acquainted with some SQL Parser, maybe the Microsoft.SqlServer.SMO.
Try to add the following code, I assume you are working with entity framework:
List<State> states = new List<State>()
{
new State { Id = 1, Code = "AL", Name = "Alabama" },
new State { Id = 2, Code = "AK", Name = "Alaska" }
};
StateDBEntities context = new StateDBEntities();
foreach (State state in states)
{
context.State.Add(state);
}
context.SaveChanges();
List<State> states = new List<State>();
using (SqlConnection connection = new SqlConnection("conn_string"))
{
string query = "SELECT Id, Code, Name FROM State";
using (SqlCommand command = new SqlCommand(query, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
State state = new State { Id = (int)reader["Id"], Code = reader["Code"].ToString(), Name = reader["Name"].ToString() };
states.Add(state);
}
}
}
}
Call the select query(here I'm writing the query, but it should be avoided, you can use Stored Procedure). Get all columns using ExecuteReader and add all the rows to list one by one.
my problem is very common, but I have not found any solution.
This is my code:
public async Task<QueryResult> RollbackQuery(ActionLog action)
{
var inputParameters = JsonConvert.DeserializeObject<Parameter[]>(action.Values);
var data = DeserailizeByteArrayToDataSet(action.RollBackData);
using (var structure = PrepareStructure(action.Query, action.Query.DataBase, inputParameters))
{
//_queryPlanner is the implementor for my interface
return await _queryPlanner.RollbackQuery(structure, data);
}
}
I need to load DataTable (from whereever) and replace data to database. This is my Rollback function. This function use a "CommandStructure" where I've incapsulated all SqlClient objects. PrepareStructure initialize all objects
//_dataLayer is an Helper for create System.Data.SqlClient objects
//ex: _dataLayer.CreateCommand(preSelect) => new SqlCommand(preSelect)
private CommandStructure PrepareStructure(string sql, string preSelect, DataBase db, IEnumerable<Parameter> inputParameters)
{
var parameters = inputParameters as IList<Parameter> ?? inputParameters.ToList();
var structure = new CommandStructure(_logger);
structure.Connection = _dataLayer.ConnectToDatabase(db);
structure.SqlCommand = _dataLayer.CreateCommand(sql);
structure.PreSelectCommand = _dataLayer.CreateCommand(preSelect);
structure.QueryParameters = _dataLayer.CreateParemeters(parameters);
structure.WhereParameters = _dataLayer.CreateParemeters(parameters.Where(p => p.IsWhereClause.HasValue && p.IsWhereClause.Value));
structure.CommandBuilder = _dataLayer.CreateCommandBuilder();
structure.DataAdapter = new SqlDataAdapter();
return structure;
}
So, my function uses SqlCommandBuilder and DataAdapter to operate on Database.
PreSelectCommand is like "Select * from Purchase where CustomerId = #id"
The table Purchase has one primaryKey on ID filed
public virtual async Task<QueryResult> RollbackQuery(CommandStructure cmd, DataTable oldData)
{
await cmd.OpenConnectionAsync();
int record = 0;
using (var cmdPre = cmd.PreSelectCommand as SqlCommand)
using (var dataAdapt = new SqlDataAdapter(cmdPre))
using (var cmdBuilder = new SqlCommandBuilder(dataAdapt))
{
dataAdapt.UpdateCommand = cmdBuilder.GetUpdateCommand();
dataAdapt.DeleteCommand = cmdBuilder.GetDeleteCommand();
dataAdapt.InsertCommand = cmdBuilder.GetInsertCommand();
using (var tbl = new DataTable(oldData.TableName))
{
dataAdapt.Fill(tbl);
dataAdapt.FillSchema(tbl, SchemaType.Source);
tbl.Merge(oldData);
foreach (DataRow row in tbl.Rows)
{
row.SetModified();
}
record = dataAdapt.Update(tbl);
}
}
return new QueryResult
{
RecordAffected = record
};
}
I Execute the code and I don't have any errors, but the data are not updated.
variable "record" contain the right number of modified (??) record, but..... on the table nothing
can someone help me?
EDIT 1:
With SQL Profiler I saw that no query is executed on DB. Only select query on .Fill(tbl) command.
EDIT 2:
Now I have made one change:
tbl.Merge(oldData) => tbl.Merge(oldData, true)
so I see perform the expected query but, with reversed parameters.
UPDATE Purchase SET price=123 where id=6 and price=22
instead of
UPDATE Purchase SET price=22 where id=6 and price=123
I have c# code which is calling stored procedure; responsible to delete record from multiple tables. I cannot read output parameters from stored procedure in c# class, although I can read output parameter when I execute stored procedure from sql server management studio.
Stored Procedure
ALTER PROCEDURE [dbo].[DeleteFunctionsNavigation]
#FunctionID INT,
#Action_identity INT OUTPUT,
#ActionInFunction_Count INT OUT,
#Controller_identity INT OUTPUT,
#FunctionDeleted INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT #Action_identity = Navigation_FunctionInAction.ActionID
FROM Navigation_FunctionInAction
WHERE Navigation_FunctionInAction.Function_ID = #FunctionID
SELECT #ActionInFunction_Count = COUNT(Navigation_FunctionInAction.ActionID) FROM Navigation_FunctionInAction WHERE Navigation_FunctionInAction.ActionID =#Action_identity
SELECT #Controller_identity = Navigation_FunctionInController.ControllerID
FROM Navigation_FunctionInController
WHERE Navigation_FunctionInController.Function_ID = #FunctionID
DELETE FROM Navigation_FunctionHierarchy
WHERE Navigation_FunctionHierarchy.Function_IDs = #FunctionID
DELETE FROM Navigation_FunctionInAction
WHERE Navigation_FunctionInAction.Function_ID = #FunctionID
IF(#ActionInFunction_Count<=1)
Begin
DELETE FROM Navigation_FunctionAction
WHERE Navigation_FunctionAction.ActionID = #Action_identity
End
DELETE FROM Navigation_FunctionInController
WHERE Navigation_FunctionInController.ControllerID = #Controller_identity
Delete FROM Navigation_Functions
WHERE Navigation_Functions.Function_ID = #FunctionID
--Check if deleted function exist... to find if record been deleted or not .. 0 means deleted >0 means not deleted
SELECT #FunctionDeleted = COUNT(Navigation_Functions.FunctionName) FROM Navigation_Functions WHERE Navigation_Functions.Function_ID = #FunctionID
RETURN #FunctionDeleted
END
c# class
public void DeleteNavigationFunctionByID(int _FunctionNavigationID)
{
using (var dbContext = new FunctionContext())
{
List<DeleteFunctionNavigation_SP_Map> _query;
//int _functionDeleted = -1;
var Action_identity_out = new SqlParameter("Action_identity", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var ActionInFunction_Count_out = new SqlParameter("ActionInFunction_Count", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var Controller_identity_out = new SqlParameter("Controller_identity", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var FunctionDeleted_out = new SqlParameter("FunctionDeleted", SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output };
var _functionDeleted = dbContext.Database.SqlQuery<DeleteFunctionNavigation_SP_Map>("exec DeleteFunctionsNavigation #FunctionID, #Action_identity out, #ActionInFunction_Count out, #Controller_identity out, #FunctionDeleted out",
new SqlParameter("#FunctionID", _FunctionNavigationID),
Action_identity_out,
ActionInFunction_Count_out,
Controller_identity_out,
FunctionDeleted_out
);
}
}