Recently I have been working on a project to provide data for a third party application, called ParcView. The PV is used to view data source from OPC and databases. The requirement of one data source is from Oracle database.
PV provides a system configuration of SQL templates for data source in data, current, tag list and tag information, four major areas (some others are rarely used). I have done a lots for SQL database server, and some of Oracle database. Based on the recommendation, if the template SQL scripts are too complicated, it is recommended to use stored procedures as a way to provide data.
In SQL SP, data source can be directly returned by using SELECT statement. However, in Oracle, this type of return is not available. What I found is that all the data row set has to be returned by a OUT parameter SYS_REFCURSOR type. This makes it is impossible for me to implement in the same way as I did for SQL server before.
I have tried another way, view with parameters. Basically, a package is defined with functions and procedures. They are in a structure of property: get in function and set in procedure. A local variable in the package as a storage for property values. Then the view references to the functions are parameter. Before calling the view, a PL/SQL command exec is called first. This strategy is back to he none-SQL query problem. PV does not have a way to call it. As a result, this strategy hits the dead wall again.
It is really hard for me to put scripts on database server side. The lesson I learned is that the PV should problem a kind of interface based APIs to allow plugin components. Now I recall that the provider of PV does have a way to add customized data source, but we have to ask the company to write codes to do it. They will charge for the service.
Maybe I should ask the computer to provide a component to allow customized plugin to provide data source.
Thursday, October 27, 2011
Procedures in Oracle Server and SQL Server
Posted by D Chu at 7:42 PM 0 comments
Labels: C#, Design Pattern, PL/SQL, SQL
Saturday, October 15, 2011
Extension Class: LogHelperExt
I wrote a helper class for logging text messages long time ago. Recently I tried to write a document and demo project about using this helper class. During the writing process, I found that the helper class can be further enhanced.
The helper class provides some static methods for writing a message string. One of basic method takes several parameters, with ILog instance as its first parameter. I realized that actually this instance is not needed to be passed in since this is a singleton instance. Why should I pass it every time? I started to simple this method. The strategy I took is to add another helper class, called as LogHelperExt. I tried to avoid to change LogHelper because this class has been used in many places.
The new helper class contains much simple APIs. The first one is Initialize:
public class LogHelperExt { private int m_Spaces; private int m_indents; public static ILog Logger { get; private set; } public static LogHelperExt Instance { get; private set; } private LogHelperExt() : this(0) { } private LogHelperExt(int indents) { m_Spaces = 0; m_indents = indents; } public static LogHelperExt Initialize() { return Initialize(null, 0); } public static LogHelperExt Initialize(ILog log) { return Initialize(log, 0); } public static Initialize(ILog log, int indents) { if ( Instance == null ) { Instance = new LogHelperExt(indents); Logger = log; } } ... }
The Initialize method is to pass ILog instance in. This method is normally used once. An additional indent value is passed for a new feature of indenting spaces for logged messages.
The commonly used API for writing messages is as followings:
public LogHelperExt WriteMessage(string flags, LogType logType, GetMessageDelegate getMessage) { if (getMessage != null ) { LogHelper.WriteMessage(Logger, flags, logType, delegate() { return string.format("{0}{1}", m_Spaces > 0 new string(' ', m_Spaces) : "", getMessage): } } return this; }
This interface is much cleaner than before. Notice that the API method is an instance method with data type of the class itself. I intended to design this class in this way, fluent interface pattern, so that I can chain the calls just in one line.
The indention and un-indention feature are added to this class:
public LogHelperExt Indent() { m_Spaces += m_indents; return this; } public LogHelperExt Unindent { m_Spaces -= m_indents; if ( m_Spaces < 0 ) { m_Spaces = 0; } return this; }
With above changes, I will use LogHelperExt for logging messages. Here is the example I wrote in my demo project:
class DemoClass { public void TestMethod() { LogHelperExt.Instance.WriteMessage("d", LogType.Debug, "Enter TestMethod").Indent(); ... LogHelperExt.WriteMessage("d", LogType.Debug, "Test message"); ... LogHelperExt.Instance.UnIndent().WriteMessage("d", LogType.Debug, "Leaving TestMethod"); } }
Posted by D Chu at 7:34 PM 0 comments
Labels: C#, Design Pattern
Wednesday, October 05, 2011
We'll Never Hear Steve Jobs Live Voice
Today is a sad day. Steve Jobs passes away, at his age 56. I wrote a blog in my Chinese blog to remember him.
It is too sad to hear the news. Personally, I feel that Apple and Steve Jobs do change my life. Not just only a computer or device like iMac or iPad or iPhone, Steve Jobs' life and his legacy have trenmendous impact on me for everything, in addition to my pursuing my software development knowledge and skills in Mac OS and iOS.
I am so fortunate to start my journey to use Apple product while Steve Jobs was alive (in year 2007). It has been an amazing experience. I just begin my new journey, and it will continue on.
Posted by D Chu at 10:07 PM 0 comments
Labels: iOS Development, Mac
Saturday, October 01, 2011
Json.Net Issue: does not support namespace in XML
Yesterday I had a talk to a developer at work. She came from the same city as my hometown where I was grown up. She was working on a project to import thousands of XML files SQL database. I recommended my dotNetCommonLibrary.dll, where I have a wrapper class for Json.Net. The wrapper class provides several APIs to convert XML string to an instance of a class and vice versa. I have used this feature to convert many application XML configuration settings to instances.
However, when I saw her XML files, I noticed that those XML files contains namespaces, which are used in XML nodes as prefix. I had never tried those types of XML documents before. Today I tried a simple XML file with a namespace for testing. Unfortunately, it looks like that Json.Net converter does not support XML with namespaces.
Example of XML with namespaces:
<?xml version="1.0" encoding="UTF-8" ?> <Root> <b:Log xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' > ... </b:Log> </Root>
I think this type XML files are very common. I have to find out a way to remove namespaces and use only local names in XML notes for instance mapping by Json.Net
It was a good talk. At least I find my wrapper class has to provide an API to remove namespaces from an XML string.
References
- Json.NET
- SO: What does XMLNS in XML mean?
- SO: Creating XML Elements without namesake declarations
- SO: How do I remove namespaces from XML, using Java dom?
- SO: XSLT Transform XML with Namespaces
- MSDN article: Using XSLT in .Net
Posted by D Chu at 8:36 PM 0 comments
Labels: C#, Open Source Libraries, XML