Using DataReader in Dapper with Oracle - dapper

How do I get values read values line a DataReader to read values of fields returned by multi in the following code to set the values in the Class
OracleRefCursor m_Cursor=null;
Dapper.SqlMapper.GridReader multi =null;
using (m_Conn = new OracleConnection(m_ConnectionString))
{
try
{
m_Conn.Open();
String m_LastName = "S" + "%";
String m_Id = "";
String m_EmpId = "";
var p = new OracleDynamicParameters();
p.Add(":p_LastName", m_LastName);
p.Add(":p_Id", m_Id);
p.Add(":p_EmpId", m_EmpId);
p.Add( ":p_Cursor1", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output );
using (multi = m_Conn.QueryMultiple(m_ProcedureName, param: p, commandType: CommandType.StoredProcedure))
{
}
}
catch (Exception ex)
{
String m_Error = ex.ToString();
}
}//end of using statement

From Dapper docs:
var sql =
#"
select * from Customers where CustomerId = #id
select * from Orders where CustomerId = #id
select * from Returns where CustomerId = #id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
}

Related

Can't update db using c# loop

Im trying to update rows in my table using loop, I get no error but nothing changed in my data...Thats my code.. What am I missing ?
private void updateZipInDB(List<ZipObj> zipCodeToUpdate)
{
var comm = "";
string DbConnString = ConfigurationManager.AppSettings["dbConnectionString"].ToString();
using (SqlConnection conn = new SqlConnection(DbConnString))
{
comm = "UPDATE Account SET address1_postalcode = #newVal WHERE AccountId = #accountID";
using (SqlCommand command = new SqlCommand(comm, conn))
{
conn.Open();
command.Parameters.AddWithValue("#newVal", "f");
command.Parameters.AddWithValue("#accountID", "f");
for (int i = 0; i < zipCodeToUpdate.Count; i++)
{
zipCodeToUpdate[i].NewVal + "' WHERE AccountId = '" + zipCodeToUpdate[i].AccountId + "'";
command.Parameters["#newVal"].Value = zipCodeToUpdate[i].NewVal;
command.Parameters["#accountID"].Value = zipCodeToUpdate[i].AccountId;
command.ExecuteNonQuery();
}
conn.Close();
}
}
}

Is there anyway to iterate through a Dapper DynamicParameters object?

I need to make a generic logger to record certain insert/update statements so that my testers can verify the data being inserted is correct.
My first thought was that I would just use a function that accepted DynamicParameters and I would foreach through the DynamicParameters to generate a string to list the parameter's name and value and make them easier to read for the testers.
Unfortunately, Dapper.DynamicParameters does not contain a public definition for "GetEnumerator"
Here is basic example of what I was hoping to do:
string myFormattedListofParameters = "";
foreach (var p in myDynamicParameters)
{
myFormattedListofParameters += p.Name + "=" + p.Value.ToString();
}
Try:
var sb = new StringBuilder();
foreach (var name in p.ParameterNames)
{
var pValue = p.Get<dynamic>(name);
sb.AppendFormat("{0}={1}\n", name, pValue.ToString());
}
string ParametersToString(DynamicParameters parameters)
{
var result = new StringBuilder();
if (parameters != null)
{
var firstParam = true;
var parametersLookup = (SqlMapper.IParameterLookup)parameters;
foreach (var paramName in parameters.ParameterNames)
{
if (!firstParam)
{
result.Append(", ");
}
firstParam = false;
result.Append('#');
result.Append(paramName);
result.Append(" = ");
try
{
var value = parametersLookup[paramName];// parameters.Get<dynamic>(paramName);
result.Append((value != null) ? value.ToString() : "{null}");
}
catch
{
result.Append("unknown");
}
}
}
return result.ToString();
}
One line with Linq:
string.Join(", ", from pn in sprocParams.ParameterNames select string.Format("#{0}={1}", pn, (sprocParams as SqlMapper.IParameterLookup)[pn]))
I'm using that to log with log4net:
Log.InfoFormat("Exec {0} {1}", storedProc, string.Join(", ", from pn in sprocParams.ParameterNames select string.Format("#{0}={1}", pn, (sprocParams as SqlMapper.IParameterLookup)[pn])));
Just in case,
var pmaster = new Dapper.DynamicParameters();
SortedList l = new SortedList();
l.Add("param1", object1);
l.Add("param2", object2);
l.Add("param3", object3);
l.Add("param4", object4);
foreach(var key in l.Keys)
{
var val = l[key];
pmaster.Add(key.ToString(), val);
}
Worked for me.

How to retrieve parentaccountid from account using queryexpression and silverlight

My query returns account.name, account.account and account.parentaccountid.
I'm using Silverlight and CRM2011.
Now I'm having trouble to find out how to extract value from parentaccountid attribute.
I have silverlightextensionmethods.cs file included in my VS project, and I'm using GetAttributeValue<Guid>("parentaccountid") to get the value from parentaccountid.
The value returned is empty.
Has anyone any ideas how to accomplish this?
I can get any other attribute value, but parentaccountid in account and parentcustomerid in contact are making my life very difficult.
Code:
FIRST I CREATE QUERYEXPRESSION:
string temp="name;accountid;parentaccountid";
string[] fields = temp.Split(';');
QueryExpression query = new QueryExpression()
{
EntityName = entity,
ColumnSet = new ColumnSet { Columns = new System.Collections.ObjectModel.ObservableCollection<string>(fields) },
Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = parentidfield,
Operator = ConditionOperator.Equal,
Values = { id }
}
}
}
};
OrganizationRequest req = new OrganizationRequest();
req.RequestName = "RetrieveMultiple";
req["Query"] = query;
service.BeginExecute(req, new AsyncCallback(GetChildren_ExecuteCallBack), service);
NEXT I TY TO READ VALUES FORM RESPONSE
void GetChildren_ExecuteCallBack(IAsyncResult childresult)
{
List<TreeRecord> listc = new List<TreeRecord>();
try
{
OrganizationResponse childresponse = ((IOrganizationService)childresult.AsyncState).EndExecute(childresult);
EntityCollection childresults = (EntityCollection)childresponse["EntityCollection"];
if (childresults.Entities.Count > 0)
{
TreeConfig sitm = new TreeConfig();
string sdisplay = "";
string[] fields = "".Split(';');
string sid = "";
string pid = "";
foreach (Entity childentity in childresults.Entities)
{
foreach (TreeConfig sitem in Configs)
{
if (sitem.EntityName == childentity.LogicalName)
{
sitm = sitem;
}
}
TreeRecord childitem = new TreeRecord();
string sValue = "";
sdisplay = "name;accountid;parentaccountid";
fields = sdisplay.Split(';');
sid = "accountid";
pid = "parentaccountid";
int i = sdisplay.Split(';').Length;
for (int j = 0; j < i; j++)
{
try { sValue += childentity.GetAttributeValue<string>(fields[j]) + " "; }
catch (Exception ex)
{
//s = "sValue haku: " + ex.Message.ToString();
//this.ReportMessage(s.ToString());
}
}
childitem.Name = sValue;
childitem.EntityName = childentity.LogicalName;
childitem.Level = sitm.Level;
childitem.ParentEntityName = sitm.EntityName;
childitem.Color = sitm.Color;
childitem.RecordId = childentity.GetEntityId<Guid>(sid);
try { childitem.ParentId = childentity.GetAttributeValue<Guid>(pid); }
catch
{
//sb.AppendLine("guid: parentid tietoa ei löydy");
//this.ReportMessage(sb.ToString());
}
listc.Add(childitem);
}
}
}
Instead of
childentity.GetAttributeValue<Guid>(pid)
use
childentity.GetAttributeValue<EntityReference>(pid)

ODP.NET Oracle.DataAccess ArrayBindCount OUT Array parameters exception handling

my scenario:
helper = new OracleHelper();
helper.CreateAndOpenConnection();
//cmd = new OracleCommand("PCK_JOBS.ARRAY_INSERT", helper.OracleHelperConnection);
cmd = new OracleCommand("PCK_JOBS.SCALAR_INSERT", helper.OracleHelperConnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
cmd.ArrayBindCount = 3;
var paramNames = new OracleParameter();
paramNames.ParameterName = "P_JOB_TITLE";
paramNames.Size = 3;
paramNames.OracleDbType = OracleDbType.Varchar2;
paramNames.Value = new string[3] { "1", "2", "3" };
cmd.Parameters.Add(paramNames);
paramNames = new OracleParameter();
paramNames.ParameterName = "O_JOB_ID";
paramNames.Size = 3;
paramNames.Direction = ParameterDirection.Output;
paramNames.OracleDbType = OracleDbType.Int32;
paramNames.Value = new int[3] { 0, 0, 0 };
cmd.Parameters.Add(paramNames);
try
{
cmd.ExecuteNonQuery();
}
catch (Exception exc)
{
}
var outParams = cmd.Parameters[1];
when PL-SQL procedure fails for example inserting row 2, and consequently ExecuteNonQuery catch, my output parameters (outParams) are all set to 0 (init value), also for rows correctly processed by procedure.
Is there a way to handle correctly this? so having the partial OUT array parameters correctly filled?
This is what I was referring to in the other thread; handle the exception in the pl/sql:
create or replace
PROCEDURE TESTDATA(myArrayNo in number , myOutputArray out varchar2)
is
customException EXCEPTION;
PRAGMA EXCEPTION_INIT( customException, - 20101 );
begin
myOutputArray := chr( myArrayNo );
if mod( myArrayNo, 2 ) = 0 then
raise customException;
end if;
exception
when customException then
myOutputArray := 'I am invalid';
end TESTDATA;
but only capture expected errors here, ones that you don't want to stop the progression, if you put in a when others... then things may get hairy and hide bugs and allow bulk updates/inserts that you don't want to allow.
c# code:
...
int[] myArrayNo = new int[3]{65, 66, 67};
String[] myOutputArray ;
OracleConnection connection = new OracleConnection(connectStr);
OracleCommand command = new OracleCommand (
"TESTDATA", connection);
//insert into dept values (:deptno, :deptname, :loc)
// Set the Array Size to 3. This applied to all the parameter in
// associated with this command
command.ArrayBindCount = 3;
command.CommandType = CommandType.StoredProcedure ;
command.BindByName = true;
// deptno parameter
OracleParameter arrayNoParam = new OracleParameter("myArrayNo",OracleDbType.Int32);
arrayNoParam.Direction = ParameterDirection.Input;
arrayNoParam.Value = myArrayNo;
command.Parameters.Add(arrayNoParam);
OracleParameter arrayOutParam = new OracleParameter();
arrayOutParam.ParameterName = "myOutputArray" ;
arrayOutParam.Direction = ParameterDirection.Output ;
arrayOutParam.ArrayBindSize = new int[3] { 50, 50, 50 };
arrayOutParam.OracleDbTypeEx = OracleDbType.Varchar2 ;
command.Parameters.Add(arrayOutParam);
try
{
connection.Open();
command.ExecuteNonQuery();
myOutputArray = (String[])command.Parameters["myOutputArray"].Value ;
for (int i = 0; i < 3; i++){
Console.WriteLine("myOutputArray{0} = {1}",
i, myOutputArray[i]);
}
}
catch (OracleException e)
{
Console.WriteLine("OracleException {0} occured", e.Message);
if (e.Number == 24381)
for (int i = 0; i < e.Errors.Count; i++){
Console.WriteLine("Array Bind Error {0} occured at Row Number {1}",
e.Errors[i].Message, e.Errors[i].ArrayBindIndex);
}
}
and outputs
myOutputArray0 = A
myOutputArray1 = I am invalid
myOutputArray2 = C
You can also use this
cmd.ArrayBindCount = length;
Oracle.DataAccess.Client.OracleParameter P_FinVslCd = new Oracle.DataAccess.Client.OracleParameter("ic_fin_vsl_code", Oracle.DataAccess.Client.OracleDbType.Varchar2);
P_FinVslCd.Direction = ParameterDirection.Input;
P_FinVslCd.Value = ArrFinVslCd;
cmd.Parameters.Add(P_FinVslCd);

InvokeOperation entities become null

This is my method :-
[Invoke]
public List<FamilyEvent> GetFamilyEvents(int userId)
{
List<FamilyEvent> familyEvents = new List<FamilyEvent>();
int id = -1; //just to fool ria
//this is for birthday reminders.
var qry = ((from member in this.ObjectContext.TreeMembers.Where(m => m.UserId == userId && m.Birthdate == null)
select member.TreeMemberId).Except(from item in this.ObjectContext.FamilyEvents where item.ReminderType ==
FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.BIRTHDAY_REMINDER
select item.TreeMemberId));
var mainQry = from mainMember in this.ObjectContext.TreeMembers
where qry.Contains(mainMember.TreeMemberId)
select mainMember;
foreach (var item in mainQry)
{
FamilyEvent familyEvent = new FamilyEvent
{
FamilyEventId = id--,
TreeMemberId = item.TreeMemberId,
RelatedTreeMemberId = -1,
ReminderType = FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.BIRTHDAY_REMINDER
};
familyEvent.TreeMember = item;
familyEvents.Add(familyEvent);
}
//this is for anniversary events
qry = ((from member in this.ObjectContext.TreeMembers.Where(m => m.UserId == userId && m.RelationId == (short)Relations.Partner)
select member.TreeMemberId).Except(from item in this.ObjectContext.FamilyEvents where item.ReminderType == FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.ANNIVERSARY_REMINDER
select item.TreeMemberId));
mainQry = from mainMember in this.ObjectContext.TreeMembers.Include("RelatedTreeMember")
where qry.Contains(mainMember.TreeMemberId)
select mainMember;
foreach (var item in mainQry)
{
FamilyEvent familyEvent = new FamilyEvent
{
TreeMemberId = item.TreeMemberId,
TreeMember = item,
RelatedTreeMemberId = item.RelatedTreeMemberId,
ReminderType = FMT.Data.Web.Helpers.Global.FAMILY_EVENTS_REMINDERS.ANNIVERSARY_REMINDER
};
familyEvent.RelatedTreeMember = item.RelatedTreeMember;
familyEvents.Add(familyEvent);
}
return familyEvents;
}
As you can see i programmatically populate the entities and populate it. When i put breakpoint on return familyEvents, i can see the correct data. However on client side, the TreeMember and RelatedTreeMember value become null. Why is it so? If i do not use [Invoke] and instead use [Query] it works, but i need Invoke in my case.

Resources