this is my first time playing with WCF in visual studio (2015), and I am running into some problems.
I have my database hosted in appharbor. I managed to insert new items into the database with:
public Test Insert (Test TestTable)
{
SqlConnection conGet = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(connectionString, conGet);
cmd.Parameters.AddWithValue("#testID", testTable.testID);
cmd.Parameters.AddWithValue("#testName", testTable.testName);
conGet.Open();
cmd.CommandText = "INSERT INTO TestTable (testID, testName) VALUES (#testID, #testName)";
cmd.ExecuteScalar();
conGet.Close();
return testTable;
}
PROBLEM: when I tried to select from it:
public Test GetData(Test test)
{
SqlConnection conPut = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("SELECT * FROM TestTable", conPut);
conPut.Open();
SqlDataReader rd = cmd.ExecuteReader();
if (rd.Depth>0)
{
while (rd.Read())
{
test.testID = (int)rd["testID"];
test.testName = rd["testName"].ToString();
}
}
else
{
Console.WriteLine("No rows found.");
}
conPut.Close();
return test;
}
rd (SqlDataReader) is not reading anything and just returns a null value, even though the test table has rows in it.
Please give me some pointers? I have tried several methods online, and no luck.. Thank you!
Remove that test for Depth. The Sql DataProvider doesn't support that property. It is always zero
Source: MSDN SqlDataReader.Depth
The outermost table has a depth of zero. The .NET Framework Data
Provider for SQL Server does not support nesting and always returns
zero.
If you want to test the condition of no rows then use the property HasRows
SqlDataReader rd = cmd.ExecuteReader();
if (rd.HasRows)
{
while (rd.Read())
{
test.testID = (int)rd["testID"];
test.testName = rd["testName"].ToString();
}
}
else
{
Console.WriteLine("No rows found.");
}
Related
I have two JDBC SQL prepared statements in the program to UPDATE tables (different areas of program). When I run the statement, I can see the updates in MySQL when I query the table. So I know the update is happening. However, I have a table connected to the DB in the program that does not show the updated results unless I stop running the program and restart it. Then the updates show in the table. I have other prepared statements that use INSERT INTO and these changes show up right away in the tables (I don't have to stop-restart my program). I don't know if the problem lies in the UPDATE, or in my code (the usual culprit), or some setting I have wrong. I think I might be passing things wrong between method calls. This is part of what it does: I have an income table, the user creates a new income listing, and part of that listing gets sent to a FUNDS table (with the UPDATE statement) and another part gets sent to an INCOME table (with the INSERT INTO statement). Here is the code, thanks for help and suggestions!
//Get user info
Income income = new Income();
Funds fund = new Funds();
income.setIncomeName(jTextField10.getText());
String budgetAmt = jTextField11.getText();
BigDecimal bAmt = new BigDecimal(budgetAmt);
income.setAmount(bAmt);
income.setDescription(jTextArea3.getText());
String iDate = jTextField12.getText();
Date date = new SimpleDateFormat("MM-dd-yy", Locale.ENGLISH).parse(iDate);
java.util.Date utilDate = date;
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
income.setDateReceived(sqlDate);
s = (String)jList10.getSelectedValue().toString();
income.setFundAllocation(s);
// Send info to be processed in FUND table with UPDATE - start of problem area
FundsSvcJDBCImpl fundImpl = new FundsSvcJDBCImpl();
Funds calculateFundAmt = fundImpl.calculateFundAmt(fund, income);
// Send info to be process in INCOME table - this part works
IncomeSvcJDBCImpl budgetImpl = new IncomeSvcJDBCImpl();
Income addIncome = budgetImpl.addIncome(income);
//This is the part of the FundsSvcJDBCImpl that uses the UPDATE statement
public Funds calculateFundAmt (Funds fund, Income income) throws Exception {
Statement stmt = null;
int max = 0;
BigDecimal fundTotal = new BigDecimal(0);
Connection conn = getConnection();
try{
stmt = conn.createStatement();
String sql1 = "SELECT sum(Amount) As fundTotal FROM funds WHERE FundsName = ?";
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
pstmt1.setString(1, income.getFundAllocation());
ResultSet rs2 = pstmt1.executeQuery();
while(rs2.next()){
fundTotal = fundTotal.add(rs2.getBigDecimal("fundTotal"));
}
fundTotal = fundTotal.add(income.getAmount());
String sql2 = "UPDATE funds SET Amount = ? WHERE FundsName = ?";
PreparedStatement pstmt = conn.prepareStatement(sql2);
pstmt.setBigDecimal(1, fundTotal);
pstmt.setString(2, income.getFundAllocation());
pstmt.executeUpdate();
}
catch (Exception e){
throw e;
}
finally {
if (conn != null){
conn.close();
stmt.close();
}
}
return fund;
}
I'm using the newly released Managed ODP.NET driver from Oracle to connect to my database (see here). Connection setup is fine. I now try to use a very simple LINQ to SQL example. The problem is that I get the an ArgumentOutOfRangeException. It appears on the foreach-Statement.
My very simple object:
[Table(Name = "my_mgr.ADDRESS")]
public class Address
{
[Column(Name = "NAME")]
public string Surname;
[Column(Name = "VNAME")]
public string Forename;
[Column(Name = "ANZ")]
public int Anz;
}
The part of testing the query:
DataContext db = new DataContext(inst.Connection);
Table<Address> addressTable = db.GetTable<Address>();
if (addressTable != null)
{
//"SELECT * from my_mgr.ADDRESS WHERE anz > 0";
var query = from p in addressTable where p.Anz > 0 select p;
foreach (var p in query)
{
MessageBox.Show(
"Forename: " + p.Forename + "\n" +
"Surname: " + p.Surname
);
}
}
Whereas my original SQL query was (which is actually working):
SELECT * from my_mgr.ADDRESS WHERE anz > 0
I actually searched a lot for this but I cannot find valid results since the driver is very new and it seems nobody had the problem before. I am very sure that the driver supports LINQ to SQL, as stated on this website. Sadly I'm not able to use neither the Entity Framework nor auto-generation tools provided by Visual Studio.
Linq to SQL does not support Oracle. If you want to use ODP.NET and Linq just like linq to sql, I suggest you use ALinq. http://www.alinq.org
Note: I'm specifically not using Fluent NHibernate but am using 3.x's built-in mapping style. However, I am getting a blank recordset when I think I should be getting records returned.
I'm sure I'm doing something wrong and it's driving me up a wall. :)
Background / Setup
I have an Oracle 11g database for a product by IBM called Maximo
This product has a table called workorder which lists workorders; that table has a field called "wonum" which represents a unique work order number.
I have a "reporting" user which can access the table via the maximo schema
e.g. "select * from maximo.workorder"
I am using Oracle's Managed ODP.NET DLL to accomplish data tasks, and using it for the first time.
Things I've Tried
I created a basic console application to test this
I added the OracleManagedClientDriver.cs from the NHibernate.Driver on the master branch (it is not officially in the release I'm using).
I created a POCO called WorkorderBriefBrief, which only has a WorkorderNumber field.
I created a class map, WorkorderBriefBriefMap, which maps only that value as a read-only value.
I created a console application with console output to attempt to write the lines of work orders.
The session and transaction appear to open correct,
I tested a standard ODP.NET OracleConnection to my connection string
The Code
POCO: WorkorderBriefBrief.cs
namespace PEApps.Model.WorkorderQuery
{
public class WorkorderBriefBrief
{
public virtual string WorkorderNumber { get; set; }
}
}
Mapping: WorkorderBriefBriefMap.cs
using NHibernate.Mapping.ByCode;
using NHibernate.Mapping.ByCode.Conformist;
using PEApps.Model.WorkorderQuery;
namespace ConsoleTests
{
public class WorkorderBriefBriefMap : ClassMapping<WorkorderBriefBrief>
{
public WorkorderBriefBriefMap()
{
Schema("MAXIMO");
Table("WORKORDER");
Property(x=>x.WorkorderNumber, m =>
{
m.Access(Accessor.ReadOnly);
m.Column("WONUM");
});
}
}
}
Putting it Together: Program.cs
namespace ConsoleTests
{
class Program
{
static void Main(string[] args)
{
NHibernateProfiler.Initialize();
try
{
var cfg = new Configuration();
cfg
.DataBaseIntegration(db =>
{
db.ConnectionString = "[Redacted]";
db.Dialect<Oracle10gDialect>();
db.Driver<OracleManagedDataClientDriver>();
db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
db.BatchSize = 500;
db.LogSqlInConsole = true;
})
.AddAssembly(typeof(WorkorderBriefBriefMap).Assembly)
.SessionFactory().GenerateStatistics();
var factory = cfg.BuildSessionFactory();
List<WorkorderBriefBrief> query;
using (var session = factory.OpenSession())
{
Console.WriteLine("session opened");
Console.ReadLine();
using (var transaction = session.BeginTransaction())
{
Console.WriteLine("transaction opened");
Console.ReadLine();
query =
(from workorderbriefbrief in session.Query<WorkorderBriefBrief>() select workorderbriefbrief)
.ToList();
transaction.Commit();
Console.WriteLine("Transaction Committed");
}
}
Console.WriteLine("result length is {0}", query.Count);
Console.WriteLine("about to write WOs");
foreach (WorkorderBriefBrief wo in query)
{
Console.WriteLine("{0}", wo.WorkorderNumber);
}
Console.WriteLine("DONE!");
Console.ReadLine();
// Test a standard connection below
string constr = "[Redacted]";
OracleConnection con = new OracleConnection(constr);
con.Open();
Console.WriteLine("Connected to Oracle Database {0}, {1}", con.ServerVersion, con.DatabaseName.ToString());
con.Dispose();
Console.WriteLine("Press RETURN to exit.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error : {0}", ex);
Console.ReadLine();
}
}
}
}
Thanks in advance for any help you can give!
Update
The following code (standard ADO.NET with OracleDataReader) works fine, returning the 16 workorder numbers that it should. To me, this points to my use of NHibernate more than the Oracle Managed ODP.NET. So I'm hoping it's just something stupid that I did above in the mapping or configuration.
// Test a standard connection below
string constr = "[Redacted]";
OracleConnection con = new Oracle.ManagedDataAccess.Client.OracleConnection(constr);
con.Open();
Console.WriteLine("Connected to Oracle Database {0}, {1}", con.ServerVersion, con.DatabaseName);
var cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandText = "select wonum from maximo.workorder where upper(reportedby) = 'MAXADMIN'";
cmd.CommandType = CommandType.Text;
Oracle.ManagedDataAccess.Client.OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetString(0));
}
con.Dispose();
When configuring NHibernate, you need to tell it about your mappings.
I found the answer -- thanks to Oskar's initial suggestion, I realized it wasn't just that I hadn't added the assembly, I also needed to create a new mapper.
to do this, I added the following code to the configuration before building my session factory:
var mapper = new ModelMapper();
//define mappingType(s) -- could be an array; in my case it was just 1
var mappingType = typeof (WorkorderBriefBriefMap);
//use AddMappings instead if you're mapping an array
mapper.AddMapping(mappingType);
//add the compiled results of the mapper to the configuration
cfg.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
var factory = cfg.BuildSessionFactory();
I have the following LINQ query
QueryResult<List<PersonDemographic>> members = new QueryResult<List<PersonDemographic>>();
var query = (from ms in this.Session.Query<MemberSummary>()
where ms.NameSearch.StartsWith(firstName.ToUpper())
&& ms.NameSearch2.StartsWith(lastName.ToUpper())
select new PersonDemographic
{
FirstName = ms.FirstName.ToProperCase(),
LastName = ms.LastName.ToProperCase(),
PersonId = ms.Id,
Address = new Address
{
Line1 = ms.AddressLine1.ToProperCase(),
Line2 = ms.AddressLine2.ToProperCase(),
City = ms.City.ToProperCase(),
State = ms.State,
Zipcode = ms.Zipcode,
},
PhoneNumber = new PhoneNumber
{
Number = string.IsNullOrWhiteSpace(ms.PhoneNumber) ? null : Regex.Replace(ms.PhoneNumber, #"(\d{3})(\d{3})(\d{4})", "$1-$2-$3")
}
});
if (this.Session.Transaction.IsActive)
{
members.Data = query.Distinct().Take(15).ToList();
}
else
{
using (var transaction = this.Session.BeginTransaction())
{
members.Data = query.Distinct().Take(15).ToList();
transaction.Commit();
}
}
The code is running under the transaction section. If I use it without a Distinct I have no problem. Adding the Distinct gives me an exception
{"Expression type 10005 is not supported by this SelectClauseVisitor."}
I can't find anything definitive. Can anyone help?
Thanks,
Paul
There are lots of things in that query that NH can't possibly know how to translate to SQL:
ToProperCase (that looks like an extension method of yours)
string.IsNullOrWhiteSpace (that's new in .NET 4, NH is compiled against 3.5)
Regex.Replace (that's just not possible to do with SQL, unless you have a DB that supports it and write a Dialect for it)
I have built a common app that works with PostgreSQL and should work on Oracle.
However i'm getting strange errors when inserting records through a parametrized query.
My formatted query looks like this:
"INSERT INTO layer_mapping VALUES (#lm_id,#lm_layer_name,#lm_layer_file);"
Unlike Npgsql which documents how to use the parameters, i could not found how Oracle "prefers" them to be used. I could only find :1, :2, :3, for example.
I do not wanto use sequential parameters, i want to use them in a named way.
Is there a way to do it? Am i doing something wrong?
Thanks
You can use named parameters with ODP.NET like so:
using (var cx=new OracleConnection(connString)){
using(var cmd=cx.CreateCommand()){
cmd.CommandText="Select * from foo_table where bar=:bar";
cmd.BindByName=true;
cmd.Parameters.Add("bar",barValue);
///...
}
}
I made this lib https://github.com/pedro-muniz/ODPNetConnect/blob/master/ODPNetConnect.cs
so you can do parameterized write and read like this:
ODPNetConnect odp = new ODPNetConnect();
if (!String.IsNullOrWhiteSpace(odp.ERROR))
{
throw new Exception(odp.ERROR);
}
//Write:
string sql = #"INSERT INTO TABLE (D1, D2, D3) VALUES (:D1, :D2, :D3)";
Dictionary<string, object> params = new Dictionary<string, object>();
params["D1"] = "D1";
params["D2"] = "D2";
params["D3"] = "D3";
int affectedRows = odp.ParameterizedWrite(sql, params);
if (!String.IsNullOrWhiteSpace(odp.ERROR))
{
throw new Exception(odp.ERROR);
}
//read
string sql = #"SELECT * FROM TABLE WHERE D1 = :D1";
Dictionary<string, object> params = new Dictionary<string, object>();
params["D1"] = "D1";
DataTable dt = odp.ParameterizedRead(sql, params);
if (!String.IsNullOrWhiteSpace(odp.ERROR))
{
throw new Exception(odp.ERROR);
}
Notes: you have to change these lines in ODPNetConnect.cs to set connection string:
static private string devConnectionString = "SET YOUR DEV CONNECTION STRING";
static private string productionConnectionString = "SET YOUR PRODUCTION CONNECTION STRING";
And you need to change line 123 to set environment to dev or prod.
public OracleConnection GetConnection(string env = "dev", bool cacheOn = false)