Running Code Metrics with Oracle.DataAccess

10 04 2008

I’m trying to get better at running the code metrics and being aware of how each of my assemblies stack up—a new feature in VS2008 and step for me (I’m used to using external tools and checking after the fact).

I came up with an odd bug today.  One of my libraries references Oracle’s ODP.NET library: Oracle.DataAccess.  Unfortunately, the code metrics snap-in threw a fit, or so I thought, at the Oracle library.

Here’s the relevant part of the error:

Message: An error occurred while calculating code metrics for target file ‘MyLibrary.dll‘ in project MyProject.

The following error was encountered while reading module ‘Oracle.DataAccess’: Security attribute type does not have a default constructor: System.Configuration.ConfigurationPermissionAttribute, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.

At first, second, and even third glance, I blamed Oracle (I enjoy blaming Oracle); however, after a bit of dinking, I took a wild shot and added System.Configuration into my project’s references.

It worked.

Now, why in the heck does my project, that doesn’t use ANYTHING out of System.Configuration, require it to calculate code metrics? 

Is it a dependency buried deep down in Oracle.DataAccess?

*boggles*





Upgrading to Server 2008 on Dell Precision 670 #2

11 03 2008

To start out, thanks to Don Awalt who a reply to my original post and relayed that Dell posted the Adaptec CERC 1.5/6ch drivers for Server 2008.  I really appreciate that—the drivers worked like a charm (note: they also worked with Vista).

With a fully functioning hard drive, I decided to give Server 2008 another shot.

Installation

The drivers, as I said worked well, however, my Dell monitor’s SD card reader/etc. really confused the drive manager.  It would detect the drives, but they ended up being W: and below.  Unplugging the monitor’s USB cable fixed this, but caused some logistic fun as my keyboard and mouse were plugged into the monitor. ;)

After the system installed, things simply worked.

Out of the box, I needed two drivers:

  • SoundMax on-board sound drivers
  • NVidia Quadra 4400 video drivers

SoundMax Sound

My first shot was at the Windows Server 2003 x64 drivers; however, the installation crashed out.  To work around that issue, simply installing the drivers (Server Manager > Configuration > Device Manager > expand out the Sound Card > Update Drivers..) from the disk worked just fine.  The Setup added in a sound console I never used, so no real loss there.

NVidia Quadra 4400

Out of the box, the standard VGA driver is tragic to try to use, so high quality video drivers were a must.  The Quadra 4400 is on the list of approved Server 2008 and Vista hardware.  The NVidia site, unfortunately, doesn’t list Server 2008 (a quick email to customer service informed me that the Vista drivers were compatible).

The official WHQL 169.39 release for Vista x64 installed without any issues—until I kicked my second monitor on.  For some strange reason, the second monitor dragged performance to the point I could get coffee while the screen refreshed.  I backed up to the prior ForceWare (162.65) and had the same problem.  Note, this was without Glass/Aero activated.  :(  If I turned the second monitor off (in the display properties), performance kicked back up again.  *boggle*

Programs

While I could live a bit without my second monitor, I wanted to see what ran and what didn’t under Server 2008.

BlogJet – BlogJet, unfortunately, crashes out with an unhandled win32 exception.  I tried a bit of tracing and didn’t get anywhere.  Finally, I posted up to the CodingRobots forums, but no response yet.  If I didn’t PAY for BlogJet, I may not care so much, but I use it daily and really (REALLY) like it.

Windows Live Writer – Heh, in the mean time, I figured I’d try WLW again since it is out of beta.  That didn’t work.  In fact, that didn’t even install.

Apparently, I couldn’t even use WLW on XP (since I use x64).  Bummer.

Omea Reader – My primary newsreader worked just fine after I did a bit of hacking similar to how Vista works.  I expected this.

Visual Studio 2008 Team Suite – Installed like a champ (as expected).

TortoiseSVN 1.4.8.12137 x64 – Installed just fine and worked very well.

Oracle Client 11g x64– The Oracle client didn’t have a clue what I was trying to do, unfortunately.  I tried the 11g R1 (11.1.0.6.0) release for x64 Windows, but the installer kept crashing out.  Ugh.  I have a 32–bit VM that I use for Oracle work at the moment—it looks like I’ll be keeping it around.

Performance

Overall, the system responded “ok”. 

While I realize the system specs may not be the best, the 670 dragged quite a bit more than it did with Server 2003 R2 Standard.  Simply navigating around between windows took a bit more time (due to the sluggish video performance), Visual Studio starts quite well, but maybe it needs more than 4GB of memory as having a large web project really brings it to its knees.

I didn’t install everything, but what really got me was Microsoft Outlook’s performance.  I have numerous Personal Data Stores that I store mail in (from the dawn of time) and the simple act of loading those data stores set the CPU ablaze.  I assume it is a glitch, but it makes it unusable to keep Outlook all the time.  The Oracle issue was another real annoying snafu as I use the Oracle Client libraries for SQLPlus and Oracle Developer.

At this time, for me, perhaps Server 2008 is a bit TOO bleeding edge with such touchy Dell hardware and the few software vendors that haven’t kept to the knife’s edge.  In a few months, the landscape should be more intune with 2008 and the transition be a bit better.

The saving grace is that after each failure, I can simply reghost my machine back to Server 2003 R2 and all of my applications (since I don’t keep anything on my workstation).  Heh.

 





Using Reflection rather than PL/SQL…

16 01 2008

Our primary domain database, our student information system, is a packaged solution that sits on top of a huge Oracle database of hundreds of tables, strange naming conventions, and other pains. 

For me to open up SQLPlus and query up a record, like a student, and see what grade their in, who their teacher is, etc. is very time consuming (there are no stored procedures for such queries and I have no access to add them).  :( 

Because of that, and to keep with standards, I created a framework library that is used by all of .NET applications—it handles the database calls, queries, and returns.  It’s further simplified by that the library can only read from the system.

So, I found myself today, on the phone with a customer… trying to look up their class roster.  This requires fetching their SSN (I loathe asking for it), querying their teacher ID from that, doing a look up across about 8 tables to find their classes, schools, class lists, and student records—just to print a list of student names.

After finding what I needed, I finished with the call and sat trying to figure out how I could use .NET and the library for a better way—everything I need exists in our student domain objects.  I just need a quick way to get to them and their properties!

Using Will’s addiction to Reflection as motivation, I ended up with:

Student student = Student.GetStudentByStudentId(123456789);

 

foreach (PropertyInfo prop in

student.GetType().GetProperties().OrderBy(i => i.Name))

{

Console.WriteLine(“{0}\t{1}”,

prop.Name,

prop.GetValue(student, null));

}

The extension method of OrderBy is a nice touch—putting the property bag into alphabetical order and making it easier to read.

The end result looks like (given no data because… well, that’d just be bad):

The final touch was to remove the actual student Id and turn this into a “real” command line application.  I updated the parameter for GetStudentByStudentId to grab the first argument passed to it; and added some help if the argument is missing or incorrect. 

if (args.Count() > 0)

{

Student student = Student.GetStudentByStudentId(int.Parse(args[0]));

}

else

{

Console.WriteLine(“eSIS Query Tool usage: “);

       Console.WriteLine(“\tesisquerytool.exe {studentId}”);

}

It’s REALLY basic, lacks proper column formatting (something I may fix), but REALLY helpful when someone calls me up.  I realize the Oracle and Database gurus will be beside themselves by the fact that I’d rather write a .NET program than query the database directly, but IMHO, part of being a developer is also seeing the tradeoffs.  I can’t “fix” the database design, make it easier, etc.—but I can write a quick little tool to help me on the off chance someone calls and needs an answer. Isn’t that what it’s all about?





Oracle Data Access Components (ODAC) with 64-bit Development

21 11 2007

Oracle has always been kinda touchy to install.  For Windows users, the simple fact that it forced its way onto the root was an annoyance at worst.  With the 10g and higher client tools, it’s even worse—Oracle doesn’t want to control just itself, but the location of ALL applications that call it.

 

If the file path of a calling application contains characters such as parenthesis, the application will fail.  This behavior is by design and currently, according to Metalink, does not have a fix.  Why is this setup this way?  No one knows.

 

This really isn’t a rub until you install Oracle onto a 64-bit Windows machine.  64-bit Windows installs two Program Files directories, one for x64 native applications and one for x86 native/WoW applications.  Unfortunately, the x86 directory is called… “Program Files (x86)”.

 

Now, for Oracle, this isn’t a big deal.  It’s happy in its “c:\oracle” directory.  I’m sure other Oracle apps install in a similar pathing structure to avoid the Program Files directory.  So, you probably won’t see this issue on a production server.  However, what about 64-bit development workstations?  All of our programs are in the (x86)-esque directory.  What does that mean?  They fail.  Even if using the 64-bit Oracle Development tools and clients… they still fail.

 

When it fails, you receive an error message that tells you exactly what’s wrong.

 

“ORA-06413: Connection not open.”

 

Ehh.  Yeah, that’s very helpful.

 

The fix?

 

According to Oracle?  There’s nothing you can do right now, a full 64-bit implementation hasn’t been created.  They acknowledge the issue, but don’t seem to care.  The hot fixes made available a few months ago (metalink #5059238 and #4751549) only addresses 32-bit issues (and, according to forum posts, not entirely).  In addition, there are workarounds to emulate a 32-bit environment, but…  that doesn’t get you past the parenthesis issue.

 

According to the community?  Uninstall your applications and reinstall them into a different path.  For example, with Visual Studio, you need to take it out of “C:\Program Files (x86)\Visual Studio 9.0\” and place it in another directory sans-parenthesis, like “C:\DevTools\Visual Studio 9.0\”. 

 

According to trial and error?  Give up on the platform-based 8i, 9i, and 10g tools.  The 11g BETA Oracle Data Access Components (11.1.0.6.10) works.  There isn’t a 32 or 64-bit code set for this download; however, looking it the GAC, the 2.111.6.10 version of Oracle.DataAccess is registered as an x86 (32-bit) library.  If you need Client access, the 11.1.0.6.0 11g Release 1 Client for x64 also works.





Java and DIY AJAX Class This Week

10 09 2007

Sun Microsystems JavaThis week creates the summation of the past 5 weeks of our internal training that I’ve provided to our department.  We’ve covered the basics of OOP, C-esque languages like C# and Java (basics), some TDD, some web programming, some forms programming—just an introduction to development practices.

This week our entire department will be sitting a Java and DIY AJAX class using Java.  For me, it’ll be quite an experience—my JSP experience is kinda limited as the technology never really appealed to me (I’ve always been a MSFT guy).  I’m always up for a new technology and I’ve had the instructor we have scheduled—and he’s awesome.

For the rest of our staff, it will provide the basis for our they move forward since our primary student system is moving from an Oracle Forms environment to Oracle on JSP.

The cool and exciting things from the DIY AJAX class, I’ll spend some time and translate over to C# and post up.

 

Tags: ,




Oracle SQL Developer and Dell D820’s

29 08 2007

I use Oracle’s SQL Developer (previously called Raptor) as a quick interface for SQL development on Oracle.  No installation, no odd files—just have the JRE on the box and go.  However, I could NEVER get it to work on my Dell Latitude D820 on Windows XP SP2.  The screen would go black and I’d have to cold boot it. 

After several attempts (or accidents by forgetting which machine I was on) with the “black screen of death”… I finally got annoyed enough today and went in to replace the video drivers (uses the same Quadro drivers for the NVS 120M as my workstation’s Quadro FX 4400)… but the installation failed.

The NVidia drivers couldn’t find valid hardware—even though the 162.50 drivers stated that model in the release notes.  I figured they may be special, so I checked out Dell’s website and the newest drivers they had were 83.x.  Ehh.

The fix?  I used WinRAR to break the .exe archive, extracted the files out, and manually installed the drivers through the management console.  It told me that the driver I was specifying (the ‘NVidia Quadro NVS 120M&rsquo ;) was invalid and could corrupt the display—I ignored that and pushed on.  The driver went in, the screen flashed a few times, and it was done.  I reboot and everything seemed to work.

Lo and behold, SQL Developer also works—no more black screens of video unhappiness.

I combed the release notes for both SQL Developer and the drivers and couldn’t see anything that would make sense to the problem—especially since my workstation has been using the same drivers.  *sigh*

 





Enterprise Library and Oracle Stored Procedure Record Sets

27 08 2007

Perhaps I just don’t sacrifice enough innocents to Oracle daily to keep up on the odd things regarding Enterprise Library and Oracle.  Or, I’m just very lucky to have most of my projects based on Microsoft SQL Server and just expect things to work just as easily with Oracle.

So what about returning a record set in Oracle?  It requires an output cursor.  Unlike tSQL, you can’t simply write a SQL command that “SELECT * FROM Customers” and expect a dataset to be returned.  You have to associate it to a cursor and then use the Oracle type called “ref cursor” to access it.

If I was not using Enterprise Library, I could use an Oracle Connection or ODP.NET to access the OracleType.Cursor.  Unfortunately, for now at least, I want to use the default OracleClient and I want to avoid hacking the Enterprise Library (Ref #1).

On our Oracle side, let’s create a simple aggregation query that I was working on earlier that accepts three input variables: quarter, year (stored as a string ), and the identifier for the teacher.  It also has one output variable, which we’ll call resultset_out of type Types.cursorType (Ref #2).

CREATE OR REPLACE PROCEDURE GetMathData
( quarter_in IN NUMBER,
  year_in IN VARCHAR,
  sin_in IN NUMBER,
  resultset_out out TYPES.cursorType)  AS BEGIN

OPEN resultset_out FOR
SELECT
    pupil_id as StudentId,
    teacher_id as TeacherId,
    report_id,
    nvl((select ‘true’ from dual where
      question_val(pupil_id, 143, r.quarter, r.year) = ‘true’ and 
      question_val(pupil_id, 152, r.quarter, r.year) = ‘true’), ‘false’) as Rep10,
    question_val(pupil_id, 94, r.quarter, r.year) as PatternAB,
    question_val(pupil_id, 95, r.quarter, r.year) as PatternABC,
    question_val(pupil_id, 96, r.quarter, r.year) as PatternAAB,
    question_val(pupil_id, 97, r.quarter, r.year) as PatternAABB
  FROM Reports r
  WHERE r.TEACHER_ID = sin_in
    AND r.YEAR = year_in
    AND r.QUARTER = quarter_in;

END GetMathData;

From first glance, that looks fine, but there’s nothing returned.  To access our result set, we have to echo it back out using PRINT.

variable resultSet refcursor;
exec GETCIPMATHDATA(4, ‘2006-2007′, [somenumber], :resultSet);
print :resultSet;

Now that we have that taken care of, let’s use it in Enterprise Library.  Be sure to import .Data and .Common.

Database db =

DatabaseFactory.CreateDatabase(“OraDatabase”);

 

DbCommand cmd =

db.GetStoredProcCommand(“GetMathData”,

4,

“2006-2007″,

[somenumber]);

 

DataTable dt =

db.ExecuteDataSet(cmd).Tables[0];

 

GridView gv = new GridView();

gv.DataSource = dt;

gv.DataBind();

Unfortunately, this will fail.  We’re only passing three variables, not the four (the refcursor) needed.  Enterprise Library (as of 3.1 May 2007) doesn’t have a DbType for Cursor (similar to the OracleType.Cursor part of System.Data.OracleClient). 

To get it to compile, our Stored Procedure needs one more parameter.   What it needs, after trial and error, it simply a pacifier.  Placing null as the recipient of the refcursor parameter keeps it happy and compiles.

 

DbCommand cmd =

db.GetStoredProcCommand(“GetMathData”,

4,

“2006-2007″,

[somenumber],

null);

 

So, you may be wondering where the data comes from… since we’re never handling the refcursor.  From what I’ve found (which isn’t much), if you are using ExecuteDataSet, the first output cursor (resultset_out out TYPES.cursorType) that is named with “_out” will become the returned DataSet.  The fact it worked had nothing to do with technology and all to do with my variable name.  *sigh*  Also, as pointed out in Tim Hollandar’s blog, this limits you to retrieving only the “_out” cursor… and only one.

 

After all that fun, I think I’ll walk into the back room and hug the SQL Server.

 

Ref #1: For an excellent article on hacking Enterprise Library to work with ODP.NET, check out Alex’s post out on CodeProject.  Looks good and I’m sure it works—just not something I want to get into the habit of right now EVERY TIME ODP or EntLibrary updates.  Seriously though, this stuff should work out of the box. *coughEntLibTeam!cough*

 

Ref #2 : This is a custom package definition that holds the ref cursor type.  I added it using:

CREATE OR REPLACE PACKAGE Types AS
     TYPE cursorType IS REF CURSOR;
END Types;





LINQ and Full Oracle Support

2 08 2007

Unfortunately, it appears that Microsoft and Oracle still have not found a way to the light.  The latest Beta 2 is still locked to only support provisioning objects from MSSQL data sources.  Even if you have the Oracle client loaded, use OLEDB (or Oracle, tried both), and have added the database to your Data Connections list, you get an error when you try to drop a table on to the builder.

“The selected object(s) use an unsupported data provider.”

Clicking help tells us that:

This message appears when you drag items that do not use the .NET Framework Data Provider for SQL Server from Server Explorer/Database Explorer onto the Object Relational Designer (O/R Designer).

The O/R Designer supports only data connections that use the .NET Framework Provider for SQL Server. Only connections to Microsoft SQL Server or Microsoft SQL Server Database File are valid.

To correct this error:

  • Add only items from data connections that use the .NET Framework Data Provider for SQL Server to the O/R Designer.

So, for now, my class libraries will remain in tact—you can LINQ pre-created objects coming from Oracle, just not directly to Oracle tables.  I checked CodePlex and didn’t see anything yet, but I’m sure it will get there.  Enough .NET developers still code against Oracle that without support, it will be hard for organizations to buy into the transition (no one wants half–and-half coding).

 





Merging Different DataSources - Old and LINQ Ways

2 07 2007

Recently, I had to come up with a way to do lookups from an existing application (with data in a SQL Server 2005 base) to our primary database (an Oracle 10g base).  If these were in the same database, or even same server, you could join the tables and things would be pretty easy.  Unfortunately, this took two steps, but turned out to not be so bad.

Here’s an example.  Note, I’m using the Enterprise Library for pull the data down, but the true example is independent of that—feel free to use whatever connection you feel fit to use.

Database dbSandbox = DatabaseFactory.CreateDatabase(“Sandbox”);

 

string sqlSandbox = “SELECT COUNT(r.RecordId) as Count, r.DepartmentId “ +

“FROM ExceptionRecords r “ +

                  “WHERE Year = @Year “ +

                  “GROUP BY r.DepartmentId “ +

                  “ORDER BY r.DepartmentId”;

 

DbCommand cmdSandbox = dbSandbox.GetSqlStringCommand(sqlSandbox);

db.AddInParameter(cmdSandbox, “Year”, DbType.Int32, 2006);

 

DataTable dtSandbox = dbSandbox.ExecuteDataSet(cmd).Tables[0];

Now we have a DataTable object that contains our information.  However, while we have the DepartmentId, we need the Department Name for our report.  That information is not located anywhere within the SQL Server database because the application is using our standard framework to get that information at runtime.

So, let’s add a new string column to our DataTable to hold the Department name.

dtSandbox.Columns.Add(new DataColumn(“DepartmentName”, typeof (string)));

Now, we’re ready to loop through and populate that new column.

foreach (DataRow row in dtSandbox.Rows)

{

row["DepartmentName"] = Depts.GetDept(Convert.ToInt32(row["DepartmentId"])).Name;

}

We’re now free to use this DataTable for our report or add additional columns/calculations to it.

Now, what if we wanted to get a bit crazy and use LINQ instead of standard T/SQL?

SBDataContext db = new SBDataContext();

var records = from r in db.ExceptionRecords

where r.Year == 2006

orderby r.DepartmentId ascending

group r by r.DepartmentId into g

select new {

DepartmentId = g.Key,

Count = g.Count() };

So, we’ve now got a var object that contains our grouped information.  The group statement in LINQ basically says: take the information you have in “r” and group it by a column, in this case DepartmentId, and place that into a new object, called [g] (for group, for sake of simplicity).  Afterwards, we created a new var object (to be placed into records) that consisted of the grouping key (which was the DepartmentId) and a count by each DepartmentId.

For the SQL inclined, we’ll notice that the statement looks similar to our one above:

SELECT [t1].[DepartmentId], [t1].[value] AS [Count]
FROM (SELECT COUNT(*) AS [value], [t0].[ DepartmentId]
FROM [ExceptionRecords] AS [t0]
WHERE [t0].[Year] = @p0
GROUP BY [t0].[ DepartmentId]) AS [t1]

Now, we must place the DepartmentName with the record.  If we simply wanted to write it out, we could do something like:

foreach (var c in records)

{

Response.Write(String.Format(“{0} ({1}) - {2}<br/>”,

Depts.GetDept(c.DepartmentId).Name,

c.DepartmentId,

c.Count));

}

Or we could create a DataTable (since GetDataTable() has unfortunately disappeared from the current LINQ release; hopeful that it will make it’s return along with the LinqDataSource in Beta2):

DataTable dt = new DataTable();

dt.Columns.Add(new DataColumn(“Count”, typeof (Int32)));

dt.Columns.Add(new DataColumn(“DepartmentId”, typeof(Int32)));

dt.Columns.Add(new DataColumn(“DepartmentName”, typeof(string)));

 

foreach (var c in records)

{

DataRow dr = dt.NewRow();

dr["Count"] = c.Count;

dr["DepartmentId"] = c.DepartmentId;

dr["DepartmentName"] = Depts.GetDept(c.DepartmentId).Name;

dt.Rows.Add(dr);

}

Is one better than the other?  Ehh… the TSQL solution is quick, painless, and using Enterprise Library, relatively standard to support.  The LINQ solution requires almost no TSQL knowledge, allows everything to be handled by the application, but is a bit bumpy if you’re wanting to populate anything that doesn’t understand the var object.  Going from Data -> DataTable is a LOT less code than with LINQ, but eventually, perhaps, that won’t even be necessary.

 





The zen of the jump drive.

28 06 2007

Running back and forth with my laptop has increasingly gotten annoying because—it’s not my primary computer.  If I need to “work at home,” I’ve been booting up the laptop, syncronizing, shutting down and dragging it home and then repeating in reverse the next day when I get back.  It also forces me to use the laptop unless I want to continue to duplicate at home by coping files off to my desktop.

GAH.

I tried using FolderShare… and that won’t work. It’s blocked here and I’ve been informed the chances of unblocking it rival those of skiing in Hell.  Stellar.  I guess that ranks up there with them thinking the CodingRobots (for BlogJet) is a pornographic site and refusing to unblock it.

So, I’ve started trying ot put EVERYTHING on my 4GB jump drive.

  • Omea’s data files.
  • My .NET projects
  • Various reference PDFs

And then more iffy applications like QueryEx, SQL Developer, Trillian, Console2, Deepburner, Foxit, NotePad++, Paint.Net, and Reflector.

To top it off, I created an autorun.inf file that popups Launchy first, so then I can just launch from there…

Cool Launchy tips for this?  Associate more odd extensions like .sln and .rdp.  For the VS solution files, I can type the name of the solution, like “KPR” or “webstorage” and up comes Orcas and the project.  For the RDP connections, have a folder of them that I tote around, so now I can use launchy to just type the name of the server and it launches that remote desktop file. 

The idea works well for anything that is based on the .NET framework—thus is somewhat always available. 

I only have a few issues so far:

  1. The jump drive letter changes and Launchy’s index can’t keep up—I’m still working on that one, but if I stick to the same couple of computers… I’ll just make sure that the drive keeps to the same letter.  Unfortunately, the ini file is in Binary, so any type of search/replace on entry editing is down.  Ideas out there?
  2. BlogJet.  I love this tool, but it stores blog and registration information in the registry (HKCR\Software\DiFolders Software\BlogJet); this information (since the codes are in plain text anyway) just needs to be moved into an XML so it’s portable.
  3. Omea Reader still cannot be run via jump drive—only the data files.  It, like BlogJet, writes registry information—which is a bit annoying since it’s now open source.  Hopefully some kind soul will take it and pump that information out and make it portable.
  4. I have to REMEMBER not to remove the jump drive when apps, like Trillian, are running. LOL

Before someone asks, I didn’t use SVS because my home PC and work PC are different architectures (x86 at work, x64 at home).  Since SVS still doesn’t support x64 Vista… that rules that out.  If and when SVS does support it, that’ll be a far better solution for the smaller applications—plug in and “install” in a few seconds.  Now, when the 1TB jump drives come out, maybe I can tackle putting Orcas into that mode.