Connect and query database in Managed C++ using SqlConnection - c++

I'm building a project in C++ in Visual Studio 2012 and I've started by writing some classes for database access. Using SQL Server data tools I've managed to create a SQL project in my solution.
Now, my question is: How can I use the types in System::Data::SqlClient namespace to connect to the database in my code? All the examples I get are using the database as reference.
Thanks in advance

If my answer helps someone, I have used the classes SqlDataReader and SqlCommand in order to select some data from db. Note that I'm fetching the ConnectionString from an App.Config I've created earlier (how it could be done).
SqlDataReader getSqlDataReader(String ^_sql)
{
SqlDataReader ^_sqlDataReader = nullptr;
SqlConnection ^_connection = gcnew SqlConnection();
ConnectionStringSettings ^connectionSettings = ConfigurationManager::ConnectionStrings["AppDefaultConnection"];
this->_connection->ConnectionString = connectionSettings->ConnectionString;
try {
this->_connection->Open();
}
catch (Exception ^_exception)
{
Console::WriteLine("Error : " + _exception->Message);
return nullptr;
}
try
{
SqlCommand ^_sqlCommand = gcnew SqlCommand(_sql,_connection);
_sqlDataReader = _sqlCommand->ExecuteReader();
}
catch(Exception ^_exception)
{
Console::WriteLine("Error : " + _exception->Message);
return nullptr;
}
return _sqlDataReader;
}
To proper build the SQL we should be aware of the class SqlParameter (example for C#) and avoid SQL injection attacks.
To use the getSqlDataReader function:
SqlDataReader ^reader = getSqlDataReader(yourParameterizedQueryString);
List<TypeToFetch>^ data = gcnew List<TypeToFetch^>();
if(reader != nullptr && reader->HasRows)
{
TypeToFetch^ typeToFetch = gcnew TypeToFetch();
while(reader->Read())
{
// example
TypeToFetch->id = (int) reader["Id"];
TypeToFetch->name = reader["Name"]->ToString();
data->Add(typeToFetch);
}
}
This question/answer can help on INSERT.

Related

MySQL connector PreparedStatement->setString not working C++

So, basically all this code does is search the database for a user with a certain username and password, and returns a nullptr if it doesn't find one.
Gebruiker* Gebruiker_DAO::getGebruiker(string login, string wachtwoord)
{
PreparedStatement *prep_stmt = nullptr;
ResultSet *res = nullptr;
Gebruiker* gebruiker = nullptr;
int rowcount = 0;
try {
prep_stmt = dbConn->getConnection()->prepareStatement("SELECT * FROM Gebruiker WHERE Gebruiker_login = ? AND Gebruiker_wachtwoord = ?");
prep_stmt->setString(1, login);
prep_stmt->setString(2, wachtwoord);
res = prep_stmt->executeQuery();
while (res->next()) {
gebruiker = new Gebruiker(login, res->getBoolean("Gebruiker_isAdmin"), res->getString("Bedrijf"),res->getBoolean("Gebruiker_isActief"),res->getInt("Werknemer_ID"));
}
}
catch(SQLException& e) {
console.log(e.what(), console.Error);
return nullptr;
}
return gebruiker;
}
The issue is that setString throws an "std::bad_alloc at memory location ..."
Ive noticed before that trying to put a string in an SQLString also throws an error. Until now ive used a workaround by putting stuff in SQLStrings.
SQLString schema = "groep003B";
dbConn->getInstance()->setSchema(schema);
dbConn->getInstance()->connect();
For some weird reason this DOES work...
Is there something i am doing wrong? I have seen examples where people use strings, but for some reason this does not work for me... Every time i try to put a variable std::string in an SQLString it gives a memory issue.

How to create new record from web service in ADF?

I have created a class and published it as web service. I have created a web method like this:
public void addNewRow(MyObject cob) {
MyAppModule myAppModule = new MyAppModule();
try {
ViewObjectImpl vo = myAppModule.getMyVewObject1();
================> vo object is now null
Row r = vo.createRow();
r.setAttribute("Param1", cob.getParam1());
r.setAttribute("Param2", cob.getParam2());
vo.executeQuery();
getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
As I have written in code, myAppModule.getMyVewObject1() returns a null object. I do not understand why! As far as I know AppModule has to initialize the object by itself when I call "getMyVewObject1()" but maybe I am wrong, or maybe this is not the way it should be for web methods. Has anyone ever faced this issue? Any help would be very appreciated.
You can check nice tutorial: Building and Using Web Services with JDeveloper
It gives you general idea about how you should build your webservices with ADF.
Another approach is when you need to call existing Application Module from some bean that doesn't have needed environment (servlet, etc), then you can initialize it like this:
String appModuleName = "org.my.package.name.model.AppModule";
String appModuleConfig = "AppModuleLocal";
ApplicationModule am = Configuration.createRootApplicationModule(appModuleName, appModuleConfig);
Don't forget to release it:
Configuration.releaseRootApplicationModule(am, true);
And why you shouldn't really do it like this.
And even more...
Better aproach is to get access to binding layer and do call from there.
Here is a nice article.
Per Our PM : If you don't use it in the context of an ADF application then the following code should be used (sample code is from a project I am involved in). Note the release of the AM at the end of the request
#WebService(serviceName = "LightViewerSoapService")
public class LightViewerSoapService {
private final String amDef = " oracle.demo.lightbox.model.viewer.soap.services.LightBoxViewerService";
private final String config = "LightBoxViewerServiceLocal";
LightBoxViewerServiceImpl service;
public LightViewerSoapService() {
super();
}
#WebMethod
public List<Presentations> getAllUserPresentations(#WebParam(name = "userId") Long userId){
ArrayList<Presentations> al = new ArrayList<Presentations>();
service = (LightBoxViewerServiceImpl)getApplicationModule(amDef,config);
ViewObject vo = service.findViewObject("UserOwnedPresentations");
VariableValueManager vm = vo.ensureVariableManager();
vm.setVariableValue("userIdVariable", userId.toString());
vo.applyViewCriteria(vo.getViewCriteriaManager().getViewCriteria("byUserIdViewCriteria"));
Row rw = vo.first();
if(rw != null){
Presentations p = createPresentationFromRow(rw);
al.add(p);
while(vo.hasNext()){
rw = vo.next();
p = createPresentationFromRow(rw);
al.add(p);
}
}
releaseAm((ApplicationModule)service);
return al;
}
Have a look here too:
http://www.youtube.com/watch?v=jDBd3JuroMQ

J2ME Stub generates an unknown exception with JPA Entity types

I created a web service stub using NetBeans 7.0 and when I try using it, it throws an unknown Exception. I don't even know what part of my code to show here, all I know is that bolded line generates an unknown Exception:
public Businesses[] findBusiness(String query) throws java.rmi.RemoteException {
Object inputObject[] = new Object[]{
query
};
Operation op = Operation.newInstance(_qname_operation_findBusiness, _type_findBusiness, _type_findBusinessResponse);
_prepOperation(op);
op.setProperty(Operation.SOAPACTION_URI_PROPERTY, "");
Object resultObj;
try {
resultObj = op.invoke(inputObject);
} catch (JAXRPCException e) {
Throwable cause = e.getLinkedCause();
if (cause instanceof java.rmi.RemoteException) {
throw (java.rmi.RemoteException) cause;
}
throw e;
}
return businesses_ArrayfromObject((Object[]) resultObj);
}
private static Businesses[] businesses_ArrayfromObject(Object obj[]) {
if (obj == null) {
return null;
}
Businesses result[] = new Businesses[obj.length];
for (int i = 0; i < obj.length; i++) {
result[i] = new Businesses();
Object[] oo = (Object[]) obj[i];
result[i].setAddress((String) oo[0]); // **exception here**
result[i].setEmail((String) oo[1]);
result[i].setId((Integer) oo[2]);
result[i].setName((String) oo[3]);
result[i].setPhoneno((String) oo[4]);
result[i].setProducts((String) oo[5]);
}
return result;
}`
I tried to consume the same webservice using a web application and it works quite well. I don't have a single clue to what is causing this exception. Any comment would be appreciated.
Update
I tried other services that return a String data type and it works fine. So I thought maybe J2ME has issues with JPA Entity types.
So my question is how do I return the data properly so that the J2ME client can read it well?

Why does SQL Server CLR procedure hang in GetResponse() call to web service

Environment: C#, .Net 3.5, Sql Server 2005
I have a method that works in a stand-alone C# console application project. It creates an XMLElement from data in the database and uses a private method to send it to a web service on our local network. When run from VS in this test project, it runs in < 5 seconds.
I copied the class into a CLR project, built it, and installed it in SQL Server (WITH PERMISSION_SET = EXTERNAL_ACCESS). The only difference is the SqlContext.Pipe.Send() calls that I added for debugging.
I am testing it by using an EXECUTE command one stored procedure (in the CLR) from an SSMS query window. It never returns. When I stop execution of the call after a minute, the last thing displayed is "Calling GetResponse() using http://servername:53694/odata.svc/Customers/". Any ideas as to why the GetResponse() call doesn't return when executing within SQL Server?
private static string SendPost(XElement entry, SqlString url, SqlString entityName)
{
// Send the HTTP request
string serviceURL = url.ToString() + entityName.ToString() + "/";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURL);
request.Method = "POST";
request.Accept = "application/atom+xml,application/xml";
request.ContentType = "application/atom+xml";
request.Timeout = 20000;
request.Proxy = null;
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
try
{
SqlContext.Pipe.Send("Calling GetResponse() using " + request.RequestUri);
WebResponse response = request.GetResponse();
SqlContext.Pipe.Send("Back from GetResponse()");
/*
string feedData = string.Empty;
Stream stream = response.GetResponseStream();
using (StreamReader streamReader = new StreamReader(stream))
{
feedData = streamReader.ReadToEnd();
}
*/
HttpStatusCode StatusCode = ((HttpWebResponse)response).StatusCode;
response.Close();
if (StatusCode == HttpStatusCode.Created /* 201 */ )
{
return "Created # Location= " + response.Headers["Location"];
}
return "Creation failed; StatusCode=" + StatusCode.ToString();
}
catch (WebException ex)
{
return ex.Message.ToString();
}
finally
{
if (request != null)
request.Abort();
}
}
The problem turned out to be the creation of the request content from the XML. The original:
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
The working replacement:
using (Stream requestStream = request.GetRequestStream())
{
using (var writer = XmlWriter.Create(requestStream))
{
entry.WriteTo(writer);
}
}
You need to dispose the WebResponse. Otherwise, after a few calls it goes to timeout.
You are asking for trouble doing this in the CLR. And you say you are calling this from a trigger? This belongs in the application tier.
Stuff like this is why when the CLR functionality came out, DBAs were very concerned about how it would be misused.

Virtual Server IIS WMI Problem

I have been tasked with finding out what is causing an issue with this bit of code:
public static ArrayList GetEthernetMacAddresses()
{
ArrayList addresses = new ArrayList();
ManagementClass mc = new ManagementClass("Win32_NetworkAdapter");
// This causes GetInstances(options)
// to return all subclasses of Win32_NetworkAdapter
EnumerationOptions options = new EnumerationOptions();
options.EnumerateDeep = true;
foreach (ManagementObject mo in mc.GetInstances(options)) {
string macAddr = mo["MACAddress"] as string;
string adapterType = mo["AdapterType"] as string;
if (!StringUtil.IsBlank(macAddr) && !StringUtil.IsBlank(adapterType))
{
if (adapterType.StartsWith("Ethernet")) {
addresses.Add(macAddr);
}
}
}
return addresses;
}
On our (Win2003) virtual servers, this works when run as part of a console application but not from a web service running on IIS (on that same machine).
Alternatively, I can use this code in a web service on IIS (on the virtual server) and get the correct return values:
public static string GetMacAddresses()
{
ManagementClass mgmt = new ManagementClass(
"Win32_NetworkAdapterConfiguration"
);
ManagementObjectCollection objCol = mgmt.GetInstances();
foreach (ManagementObject obj in objCol)
{
if ((bool)obj["IPEnabled"])
{
if (sb.Length > 0)
{
sb.Append(";");
}
sb.Append(obj["MacAddress"].ToString());
}
obj.Dispose();
}
}
Why does the second one work and not the first one?
Why only when called through an IIS web service on a virtual machine?
Any help would be appreciated.
UPDATE: After much telephone time with all different levels of MS Support, the've come to the conclusion that this is "As Designed".
Since it is on a driver level for the virtual network adapter driver, the answer was that we should change our code "to work around the issue".
This means that you cannot reliable test code on virtual servers unless you with the same code that you use on physical servers, since we can't guarantee that the servers are exact replicas...
Okay, so I wrote this code to test the issue:
public void GetWin32_NetworkAdapter()
{
DataTable dt = new DataTable();
dt.Columns.Add("AdapterName", typeof(string));
dt.Columns.Add("ServiceName", typeof(string));
dt.Columns.Add("AdapterType", typeof(string));
dt.Columns.Add("IPEnabled", typeof(bool));
dt.Columns.Add("MacAddress", typeof(string));
//Try getting it by Win32_NetworkAdapterConfiguration
ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapter");
EnumerationOptions options = new EnumerationOptions();
options.EnumerateDeep = true;
ManagementObjectCollection objCol = mgmt.GetInstances(options);
foreach (ManagementObject obj in objCol)
{
DataRow dr = dt.NewRow();
dr["AdapterName"] = obj["Caption"].ToString();
dr["ServiceName"] = obj["ServiceName"].ToString();
dr["AdapterType"] = obj["AdapterType"];
dr["IPEnabled"] = (bool)obj["IPEnabled"];
if (obj["MacAddress"] != null)
{
dr["MacAddress"] = obj["MacAddress"].ToString();
}
else
{
dr["MacAddress"] = "none";
}
dt.Rows.Add(dr);
}
gvConfig.DataSource = dt;
gvConfig.DataBind();
}
When it's run on a physical IIS box I get this:
Physical IIS server http://img14.imageshack.us/img14/8098/physicaloutput.gif
Same code on Virtual IIS server:
Virtual server http://img25.imageshack.us/img25/4391/virtualoutput.gif
See a difference? It's on the first line. The virtual server doesn't return the "AdapterType" string. Which is why the original code was failing.
This brings up an interesting thought. If Virtual Server is supposed to be an "virtual" representation of a real IIS server, why doesn't it return the same values?
Why are the two returning different results? It's possible that due to the different user accounts, you'll get different results running from the console and from a service.
Why does (1) fail and (2) work? Is it possible that a null result for adapterType return a null value? If so, would the code handle this condition?