parameterized oracle query with enterprise library - oracle

My .cs file contains this code
DbCommand dbc =
db.GetStoredProcCommand(
string.Format(ConfigurationSettings.AppSettings["INSERT_TBLREPORTTYPE"]
, rtype, zoneid, name));
and my query in web.cofig is:
<add key="INSERT_TBLREPORTTYPE"
value="INSERT INTO TBLREPORT(ID,TYPE,RELATIONID,ISACTIVE,NAME)
VALUES(SEQ_REPORT.NEXTVAL,{0},{1},0,{2}) "/>
How to add parameter so that I can prevent sql injection on my site?
I tried
db.AddInParameter(dbc, "NAME", DbType.String, name);
db.AddInParameter(dbc, "RELATIONID", DbType.Int32, zoneid);
db.AddInParameter(dbc, "TYPE", DbType.String, rtype);
and also
dbc.Parameters[0].DbType = DbType.String;
dbc.Parameters[0].Value = name;
dbc.Parameters[1].DbType = DbType.Int32;
dbc.Parameters[1].Value = zoneid;
dbc.Parameters[2].DbType = DbType.String;
dbc.Parameters[2].Value = rtype;
None of them is working. Can anyone give me suggestions regarding this????

The parameter prefix for Oracle is :. So you should change your SQL to:
<add key="INSERT_TBLREPORTTYPE"
value="INSERT INTO TBLREPORT(ID, TYPE, RELATIONID, ISACTIVE, NAME)
VALUES(SEQ_REPORT.NEXTVAL, :TYPE, :RELATIONID, 0, :NAME) "/>
Then you can add the parameters using:
db.AddInParameter(dbc, ":NAME", DbType.String, name);

Related

Update Timestamp after jdbc:inbound-channel-adapter reads a record from DB

I am using Spring integration's "int-jdbc:inbound-channel-adapter" to fetch records from the DB. However after I fetch records I also need to update 2 columns
1) Status column
2) Timestamp columns
Updating the status column is not an issue as I can use below xml snippet
<int-jdbc:inbound-channel-adapter query="select * from item where status=2"
channel="target" data-source="dataSource"
update="update item set status=10 where id in (:id)" />
However when I try to update timestamp, it doesnt work
<int-jdbc:inbound-channel-adapter query="select * from item where status=2"
channel="target" data-source="dataSource"
update="update item set status=10,timestamp=:timestamp where id in (:id)"
update-sql-parameter-source-actory="timestampUpdaterSqlParameterSourceFactory">
<int-jdbc:inbound-channel-adapter>
<bean id="timestampUpdaterSqlParameterSourceFactory"
class="org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory" >
<property name="parameterExpressions">
<map>
<entry key="timestamp" value="#now"/>
</map>
</property>
</bean>
<bean id="now" scope="prototype" class="java.sql.Timestamp">
<constructor-arg value="#{ T(java.lang.System).currentTimeMillis()}" />
</bean>
We can use DB level methods to set the time like sysdate for oracle, but I am not keen on using DB specific methods in code for testing purposes(H2 DB used for testing)
Any Help is greatly appreciated
Thanks
I had the same issue, the problem is that :timestamp expression is evaluated as a Collection Projection, check the code here.
So my Original query was something like this
update table set status = 1, published_at = :now where id_event in (:id)
After the parsing was something like this
update table set status = 1, published_at = ?, ?, ? where id_event in (?, ?, ?)
The numbers of ? is the same as the number of results from the select statement. So if the result is more than one, you get a Bad Grammar exception.
I made a not very nice solution (intrusive) using spring-integration-java-dsl
protected void addNotCollectionProjectionExpression(
ExpressionEvaluatingSqlParameterSourceFactory factory,
String key, String expression) {
try {
Field parameterExpressionsField = factory.getClass().getDeclaredField("parameterExpressions");
parameterExpressionsField.setAccessible(true);
Map<String, Expression[]> parameterExpressions = (Map<String, Expression[]>) parameterExpressionsField
.get(factory);
Field parserField = factory.getClass().getDeclaredField("PARSER");
parserField.setAccessible(true);
ExpressionParser parser = (ExpressionParser) parserField.get(factory);
Expression compiledExpression = parser.parseExpression(expression);
Expression[] expressions = new Expression[]{
compiledExpression,
compiledExpression
};
parameterExpressions.put(key, expressions);
} catch (NoSuchFieldException | IllegalAccessException e) {
logger.error("Field parameterExpressions | PARSER can not be obtained", e);
}
}
....
//how to use it
ExpressionEvaluatingSqlParameterSourceFactory factory =
new ExpressionEvaluatingSqlParameterSourceFactory();
addNotCollectionProjectionExpression(factory, "now",
"T(com.example.MyClass).staticMethod()");
return factory;
You can notice that I am avoiding to use Collection Projection using the same expression in both elements of the array.

Adding Programmatically datasource / dataset to LocalReport

Is there any way to add programmatically a datasource / dataset to a Microsoft.Reporting.WebForms.LocalReport when the report-XmlFile (*.rdlc) has no datasource / dataset definitions at design-time?
This works if I already have a datasource / dataset definition in my *.rdlc
C#
public byte[] RenderReport(string reportName, string reportFormat)
{
LocalReport report = LoadReport(reportName);
//Has same name like DataSet in *.rdlc
ReportDataSource rds = new ReportDataSource("DataSet1", getData());
report.DataSources.Clear();
report.DataSources.Add(rds);
return report.Render(reportName);
}
private DataTable getData()
{
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("ID",typeof(System.String)));
dt.Columns.Add(new DataColumn("NAME", typeof(System.String)));
dt.Rows.Add(new string[] { "1", "Me" });
return dt;
}
*.rdlc
<DataSources>
<DataSource Name="DataSource1">
<ConnectionProperties>
<DataProvider>System.Data.DataSet</DataProvider>
<ConnectString>/* Local Connection */</ConnectString>
</ConnectionProperties>
</DataSource>
</DataSources>
<DataSets>
<DataSet Name="DataSet1">
<Query>
<DataSourceName>DataSource1</DataSourceName>
<CommandText>/* Local Query */</CommandText>
</Query>
<Fields>
<Field Name="ID">
<DataField>ID</DataField>
<rd:TypeName>System.String</rd:TypeName>
</Field>
<Field Name="NAME">
<DataField>NAME</DataField>
<rd:TypeName>System.String</rd:TypeName>
</Field>
</Fields>
</DataSet>
</DataSets>
But if I remove the datasource / dataset definition I get
{Microsoft.Reporting.DefinitionInvalidException: The definition of the
report '' is invalid. --->
Microsoft.ReportingServices.ReportProcessing.ReportPublishingException:
The Value expression for the text box ‘Textbox1’ refers to the field
‘ID’. Report item expressions can only refer to fields within the
current dataset scope or, if inside an aggregate, the specified
dataset scope. Letters in the names of fields must use the correct
case.}
Do I always have to create something like a "Dummy"-DataSource/DataSet or do I miss something in my code?
I hope there is another solution as manipulating the XML before rendering-process, any ideas?
Thanks!
You can't leave RDLC witout DataSets, if you are using it and RDLC is embedded in your project.
Either you leave DataSet fixed and change only it's items either try to load report definition from XML
// Valid XML with dynamic DataSources and DataSets
string s = #"<?xml version=""1.0"" encoding=""utf-8""?><Report ...>...</Report>";
report.LoadReportDefinition(new MemoryStream(Encoding.UTF8.GetBytes(s)));
return report.Render(reportName);

Retrieve value from xml using linq

I have this XML data
<Address Location="ABC">
<Add Location="XYZ1" street="street1" />
<Add Location="VZC" street="street1" />
</Address>
I want to find out the value of <add> --> street which is street1
I have tried it as below, not getting the result
var q = from res in xmlDoc.Descendants("Address")
where res.Attribute("Location").Value == "ABC"
&& res.Element("Add").Attribute("Location").Value == "VZC"
select new
{
streetadd= res.Element("Add").Attribute("street").Value,
};
Please someone suggest how to check the condition for child element in this case.
Try this:
var query = from res in xmlDoc.Descendants("Address")
where res.Attribute("Location").Value == "ABC"
from child in res.Elements("Add")
where child.Attribute("Location").Value == "VZC"
select new
{
streetadd = child.Attribute("street").Value
};

NullReferenceException while Reading XML File with Linq (C# 4.0)

I'm completely stumped, I've used very similar code before and it worked perfectly, the XML in this was written by a separate method in this program and I checked it against it and it looked fine
That's the code for parsing the XML file
UserType CurrentUser = new UserType();
XDocument UserDoc = XDocument.Load(Path2UserFile);
XElement UserRoot = UserDoc.Element("User");
CurrentUser.User_ID = int.Parse(UserDoc.Element("User_ID").Value);
CurrentUser.Full_Name = UserDoc.Element("Full_Name").Value;
CurrentUser.Gender = UserDoc.Element("Gender").Value;
CurrentUser.BirthDate = DateTime.Parse(UserDoc.Element("Birthdate").Value);
CurrentUser.PersonType = int.Parse(UserDoc.Element("PersonType").Value);
CurrentUser.Username = UserDoc.Element("Username").Value;
CurrentUser.Password = UserDoc.Element("Password").Value;
CurrentUser.Email_Address = UserDoc.Element("Email_Address").Value;
The Path2UserFile points to the correct file as well, and I had it write out the full path.
It has a NullReferenceException whenever it tries to parse the contents of any of the elements
The XML File follows this format
<User>
<User_ID>11</User_ID>
<Full_Name>Sample User</Full_Name>
<Gender>Male</Gender>
<BirthDate>12/12/2010 12:00:00 AM</BirthDate>
<PersonType>2</PersonType>
<Username>Sample User</Username>
<Password>sample123</Password>
<Email_adddress>sampleuser#gmail.com</Email_adddress>
</User>
The UserType class looks like this
class UserType
{
public int User_ID = 0;
public string Full_Name = string.Empty;
public string Gender = string.Empty;
public DateTime BirthDate;
public int PersonType = 0;
public string Username = string.Empty;
public string Password = string.Empty;
public string Email_Address = string.Empty;
}
I have no clue as to what's wrong, any help would be very much appreciated
Change all the UserDoc references to UserRoot (the ones after the UserRoot declaration). Since the object is an XDocument rather than an XElement you need to operate at that level. Otherwise you can refer to UserDoc.Root.Element(...) instead but that's lengthier.
UserType CurrentUser = new UserType();
XDocument UserDoc = XDocument.Load(Path2UserFile);
XElement UserRoot = UserDoc.Root;
CurrentUser.User_ID = int.Parse(UserRoot.Element("User_ID").Value);
CurrentUser.Full_Name = UserRoot.Element("Full_Name").Value;
CurrentUser.Gender = UserRoot.Element("Gender").Value;
CurrentUser.BirthDate = DateTime.Parse(UserRoot.Element("BirthDate").Value);
CurrentUser.PersonType = int.Parse(UserRoot.Element("PersonType").Value);
CurrentUser.Username = UserRoot.Element("Username").Value;
CurrentUser.Password = UserRoot.Element("Password").Value;
CurrentUser.Email_Address = UserRoot.Element("Email_address").Value;
Also, be aware of your case. Use BirthDate instead of Birthdate (capital "D" to match your XML). Similarly, it's Email_address not Email_Address (lowercase "a") and your XML has 3 D's in "address" (spelling mistake).

Dealing with a null datetime element within xml using linq

HI
I have an example document that looks like
<ItemEntry>
<PurchaseDate>2010-03-18T20:36:32.81108+13:00</PurchaseDate>
<StoreGUID>0a0324ad-5f99-486a-a2d0-870bc6991e9f</StoreGUID>
<ExpiryDate />
<CardID>111111</CardID>
<PurchaseAmount>0</PurchaseAmount>
<RedeemedAmount />
<EntryType>1</EntryType>
<RedeemedDate />
<SalesAssistantID>0</SalesAssistantID>
</ItemEntry>
As you can see there are couple of elements ExpiryDate and RedeemedDate are are empty.
var q = from c in xml.Elements("ItemEntry")
select new mdDetail {
PurchaseDate = (DateTime)c.Element("PurchaseDate"),
StoreGUID = (Guid)c.Element("StoreGUID"),
ExpiryDate = (DateTime?)c.Element("ExpiryDate")??DateTime.MinValue,
CardID = (int)c.Element("CardID"),
PurchaseAmount = (double)c.Element("PurchaseAmount"),
RedeemedAmount = (double?)c.Element("RedeemedAmount"),
EntryType = (int)c.Element("EntryType"),
RedeemedDate = (DateTime?)c.Element("RedeemedDate") ??DateTime.MinValue,
SalesAssistantID = (int)c.Element("SalesAssistantID"),
}
;
foreach (var item in q)
{
}
I am not sure how to deal with the null element value,
I have tried ??DateTime.MinValue and ??null however both give me a "
String was not recognized as a valid DateTime." error.
Any suggestions?
Thank you
ExpiryDate = String.IsNullOrEmpty((string)c.Element("ExpiryDate"))?
DateTime.MinValue : DateTime.Parse((string)c.Element("ExpiryDate"))
"You could also use null instead of DateTime.MinValue if ExpireyDate is
declared to be nullable"
#Gabe, you can't just use null - you need to use (DateTime?)null because the compiler won't know how to convert null into a DateTime object
So if you want the value to just be a blank (null) this would be the final code:
ExpiryDate = String.IsNullOrEmpty(c.Element("ExpiryDate").Value)?
(DateTime?)null : DateTime.Parse(c.Element("ExpiryDate").Value)
Assuming DateTime is a declared a nullable (DateTime?)

Resources