Tuesday, July 5, 2011

Deleting TList within a TList.

I am trying to free Tlist within a Tlist in a onDestroy event and FastMM4 is raising an access violation error. Here is the code snippet.
procedure TSignalFrm.FormDestroy(Sender: TObject);
var
  x
,y: integer;
begin
 
for x := 0 to signalList.Count - 1 do
 
begin
   
for y:=0 to TSignal(SignalList.Items[x]).alarmList.Count-1 do
   
begin
     
TAlarm(TSignal(SignalList.Items[x]).alarmList.Items[y]).Free;
   
end;
   
TSignal(SignalList.Items[x]).AlarmList.Free;
   
TSignal(SignalList.Items[x]).Free;
 
end;
 
SignalList.Free;
end;
I get access violation error at TSignal(SignalList.items[x]).Free; line. Freeing AlarmList items before freeing SignalList items raises the access violation error, but WHY?
Update: I am using Delphi 7.0 on Windows XP. The actual FastMM4 messages is as follows.

FastMM has detected an attempt to call a virtual method on a freed object. An access viloation will now be raised in order to abort the current operation.
Freed Object class: TList
Virtual method: Destroy
Virtual method address:427CF0
The allocation number was: 80055
Followed by a lots of memory dump.

According to this FastMM4 error, if you free an object within an another object, you automatically free the owner as well. I know that can't be true, but correct me if I am wrong.

Answer:
Does TSignal not free its AlarmList member in its destructor? (That’s how I would do this).
Update: does it work if you remove the TSignal(SignalList.Items[x]).AlarmList.Free; line?
Second update: Each TList's items need to be freed, if it contains pointers to objects.
Your problem was that TSignal is not a TList. Since it takes care of freeing its members (such as the Alarmlist), that Alarmlist should not be freed explicitly.
 

Serial Communication (RS232) in LINUX

I am currently working with Delphi Prism for Mono development. So, the software can be cross-platform mainly to be run on Linux OS. To get started, I have been implementing and test running the basic functions of my software - Serial and Network Communication.

But I can't seem to get passed serial communication implementation for Mono. It seems that there is no library or .NET framework that supports Linux environment after searching the Internet and Stackoverflow. Although there are some similar questions that were asked by others in Stackoverflow, the answers don't really show any sample. I am kind of stuck.

Here is the code I wrote for Mono serial comm. after visiting this one website.
  {$IFDEF LINUX}
   
if SerialPort1 = nil then
       
SerialPort1 := new System.Io.Ports.SerialPort();
   
SerialPort1.Close;

   
SerialPort1.BaudRate:=19200;
   
SerialPort1.DataBits:=8;
   
SerialPort1.DtrEnable:=true;
   
SerialPort1.Parity:=System.IO.Ports.Parity.Even;
   
SerialPort1.PortName:="/dev/ttyS0";
   
SerialPort1.ParityReplace:=63;
   
SerialPort1.ReadBufferSize:=4096;
   
SerialPort1.ReadTimeout:=1000;
   
SerialPort1.RtsEnable:=true;
   
SerialPort1.StopBits:=System.IO.Ports.StopBits.One;
   
SerialPort1.WriteTimeout:=1000;
   
SerialPort1.Open;

   
while (true) do
   
begin
       
CommByte[0]:=$FF;
       
CommByte[1]:=$04;
       
CommByte[2]:=$04;
       
CommByte[3]:=thechannel;
       
CommByte[4]:=mcommand;
       
CommByte[5]:=(CommByte[2] xor CommByte[3] xor CommByte[4]);

       
SerialPort1.Write(CommByte,0,6);
       
while SerialPort1.BytesToWrite>0 do;
       
Thread.Sleep(10);
       
Application.DoEvents;
   
end;
{$ENDIF}
 
But everytime I run this code under Linux, Mono raises a message box with "The requested feature is not implemented." I can't understand why. Is this even possible to do for Mono?
I need to get access to the serial port on Linux for RS232 communication.
Thanks,

Answer:
The property ParityReplace is currently not implemented. If it is not really needed, throw it away and you won't probably have this exception. And if you need it, tell me, it could be probably be done using PARMRK and changing mark to this byte. However I have also to find an idea how to unit test it ;)

ASP.NET with Window Form Application

I am a beginner in the Dot NET environment and not really happy with it from what I have read and done with Dot NET so far.

I need to migrate or write a program that will utilize ASP.NET with window Form Application. For whatever reason, I can't create this program as a single project. Am I miss understanding what Dot NET is or is that how Dot NET designed to be?

I have Delphi Prism(DP), which is based on Visual Studio 2010. Under DP, I can only create separate projects for ASP.NET and/or Windows Form Application. I can not seem to use little bit of both world under a single project. Is it even possible to do that?

My Delphi Prism Dot NET program is supposed to be part window based and part web-based. As a window based program, it is supposed to send and receive data on the serial port and network. As a web-based, it is supposed to give the user access to the window-based (server side) of the program on the Internet or LAN or Intranet.

I ran all their demos and searched online for help. Still, I am having hard time with it.
I am getting frustrated. I thought, programming in Dot NET was going to be a breeze, but it is turning out to be a problem. I should know this by now for Dot NET being Microsoft.
If anyone can give me hints or more information to help me understand Dot NET little better, I would appreciate it. Thank you.

Answer:
They are separate projects for separate problem domains. You would not and can not intermingle an ASP.NET project and a Windows Forms project.

Choose a project type and build out something simple. After you have crossed that bridge move that concept to another project type (WPF, Silverlight, ASP.NET MVC, etc...) and note the differences.
The underlying language will carry across projects such as C#, VB, etc...however the project type/framework will not.
 

Serial Communication (RTS) and Windows 7

I am developing Delphi application on Delphi 2010 XE RAD Studio under Windows 7. My application talks on the serial port non-stop. I am using AsyncPro for Delphi 2010. Serial communication and everything else on the computer I develop with works great without any problem. However, when my release version of my application is run on another Windows 7 system, serial communication completely fails. We probed the serial communication itself for an answer and found out that Request to Send (RTS) line is not dropped right after sending all the bytes, whereas on my development computer RTS line is dropped correctly.
Even when I explicitly drop the RTS line to low or false state, RTS line doesn't drop right away but after good 15 milliseconds. Thus, serial communication on my release version is failing.
Am I missing important information about Windows 7 and serial communication issues?

UPDATE: I just found the bug with my Aysncpro 5.0 for Delphi XE. It is weird. When my Delphi XE IDE is open or running, my program is communicating flawlessly. When I shutdown or close my Delphi XE IDE while my program is running, the same program doesn't communicate very well or it times out.

Chime in if you have any idea why it is happening.
Any help will be appreciated.

Thank you,

Answer:

Sounds like a timer resolution problem to me. I had the same problem trying to write to a USB FTDI driver using an event based timer with timeSetEvent()... When Delphi loads, it changes the timer resolution to less than 20ms, which made my app work fine. When the IDE wasn't running I couldn't get things to work below 20ms +/- 5ms (the default Windows resolution I believe).

To fix the problem, I call timeBeginPeriod(1) in the thread to set the minimum system wide timer resolution.

I believe this affects the resolution of other time based events, because I get better than +/-5ms accuracy on other (non-multimedia timer) wait events in my app when I use timeBeginPeriod().
So, what I'm suggesting is that somewhere in the AsyncPro code it's using some time based event or call back... That would be affected by Delphi's change to the timer resolution when it is loaded. Try calling timeBeginPeriod(1) somewhere in your app when it starts and see if there is a change.
Oh, and don't forget to call timeEndPeriod(1) when your app shuts down.
N@

VCL TTimer stops when a window dragged or pull down menu clicked

I have TTimer enabled and is supposed to run non-stop forever until the user stop it. However, it doesn't work that way. Within OnTimerevent, it processes window messages over and over again in milliseconds.
For instance, here is a snippet of my code.


procedure TDXCommDlg.Timer2Timer(Sender: TObject);
begin
  inherited
;
 
if Scanning then
 
begin
   
Timer1.Enabled := false;
   
Timer2.Enabled := false;
     
while not PostMessage(Handle,WM_USER + 10,1234,5678) do;
     
Timer1.Enabled := true;
 
end;
end;
 
 
What happens is this. While the TTimer is enabled and running, you drag any windows of the application or click on pull down menu the TTimer event completely stops working, even though I have taken precautionary steps in other part of the code to prevent this from happening. However, it doesn't seem to be helping.
The only way to restart the OnTimer event is to stop and restart the Timer by the user through TButton event.
The same code or program works fine under Windows XP compiled with Delphi 7. Currently, I am using Windows 7 and Delphi 2010 to rebuild my system.
I will try to give you more information. What I am working on is a copyrighted software.
There is a user defined procedure called HandleMsg. It actually processes the serial port messages. HandleMsg is set to the Application event onMessage;
Application.onMessage:=HandleMsg();
PostMessage is associated with onMessage event of the application.
Whenever PostMessage is called, it fires onMessage event which is set to HandleMsg().


Here more of my code:
 procedure TDXCommDlg.HandleMsg(var
 
Msg: TMsg; var Handled: Boolean);
 
begin
     
Handled := false;
     
case Msg.message of
      WM_USER
+ 10:
             
begin
                   
if (Msg.wParam = 1111) and (Msg.lParam = 2222) then
                   
begin
                     
SendLanMessage;
                     
Handled := true;
                   
end
                   
else if (Msg.wParam = 1234) and (Msg.lParam = 5678) then
                   
begin
                       
SendMessage;
                       
Handled := true;
                   
end
                   
else
                   
begin
                     
if (Msg.wParam = 4321) then
                     
begin
                       
MainFrm.CloseWindow(TViewFrm(Msg.lParam).WinCap);
                     
end;
                   
end;
             
end;
     
end; { case } end;
HandleMsg() responds to PostMessage. Correct me if I am wrong.


 Answer:

In both cases (starting to size/move window or opening a menu) the last message dispatched from TApplication.ProcessMessage is WM_NCLBUTTONDOWN (or a WM_NCRBUTTONDOWN if caption and system menu exists and clicked on the caption.. or a WM_RBUTTONUP if opening a context menu, etc..). Common to all is they are starting a modal message loop.
For instance the below is from WM_ENTERSIZEMOVE documentation:
The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving or sizing modal loop. [....] The operation is complete when DefWindowProc returns.
After a modal message loop is started the HandleMessage call in TApplication.Run will not return until DefWindowProc for the relevant window returns (in the WM_NCLBUTTONDOWN case for instance, the dispatched message will cause a WM_SYSCOMMAND to be sent to the window which will start the modal message loop and will not return until moving/sizing is complete). So you won't be able to use an OnMessage handler of the application in this period which is called in TApplication.ProcessMessage.
Your solution is simple. Instead of using the OnMessage handler, handle the message with a message handler of your form:
const
  WMUSER_10
= WM_USER + 10;

type
 
TForm1 = class(TForm)
   
Timer1: TTimer;
    procedure
Timer1Timer(Sender: TObject);
 
private
    procedure
WmUser10(var Msg: TMsg); message WMUSER_10;
 
public
 
end;

procedure
TForm1.Timer1Timer(Sender: TObject);
begin
 
PostMessage(Handle, WMUSER_10, 1234, 5678);
end;

procedure
TForm1.WmUser10(var Msg: TMsg);
begin
 
//
end;

Or, put your code in the OnTimer event, since WM_TIMER is itself posted.

Delphi 2010 Control Flickering

I have been upgrading or migrating our software from XP OS to be able to compile and run under Windows 7. Our software is starting to show issues that we didn't notice under Windows XP. Currently, I am dealing with a user defined control flickering on a TForm. It seems to flicker every now and then not always, but when it flickers it is very noticeable. I have set DoubleBuffered for the TForm and TTrendChart Class, but it is not helping.

This a user-defined control of TCustomPanel. It is supposed to display a Live Trendchart on a TForm.

TTrendChart = class(TCustomPanel)
private
  fCount
:integer;
  fColors
:array[0..7] of TColor;
  fNames
:array[0..7] of string;
  fMinText
:string16;
  fMaxText
:string16;
  fShowNames
:Boolean;
  fMaxTextWidth
:integer;
  data
:TList;
 
Indexer:integer;
  chartRect
:TRect;
  fWidth
:integer;
  fHeight
:integer;
  firstTime
:Boolean;
 
function GetColors(Index:integer):TColor;
  procedure
SetColors(Index:integer; const value :TColor);
 
function GetNames(Index:integer):string;
  procedure
SetNames(Index:integer; const value: string);
  procedure
SetCount(const value : integer);
  procedure rShowNames
(const value : Boolean);
  procedure
SetMaxText(const value:string16);
  procedure
SetMinText(const value:string16);
  procedure
RecalcChartRect;
protected
  procedure
Resize; override;
  procedure
Paint; override;
public
  constructor
Create(AOwner : TComponent); override;
  destructor
Destroy; override;
  procedure
PlotPoints(p1,p2,p3,p4,p5,p6,p7,p8:real);
  procedure
ClearChart;
  procedure
Print;
  property
TrendColors[Index:integer]: TColor read GetColors write SetColors;
  property
TrendNames[index:integer]: string read GetNames write SetNames;
published
  property
TrendCount: Integer read fCount write SetCount default 8;
  property
ShowNames: Boolean read fShowNames write rShowNames default true;
  property
MaxText:string16 read fMaxText write SetMaxText;
  property
MinText:string16 read fMinText write SetMinText;
  property
Align;
  property
Alignment;
  property
BevelInner;
  property
BevelOuter;
  property
BevelWidth;
  property
DragCursor;
  property
DragMode;
  property
Enabled;
  property
Caption;
  property
Color;
  property
Ctl3D;
  property
Font;
  property
Locked;
  property
ParentColor;
  property
ParentCtl3D;
  property
ParentFont;
  property
ParentShowHint;
  property
PopupMenu;
  property
ShowHint;
  property
TabOrder;
  property
TabStop;
  property
Visible;

  property
OnClick;
  property
OnDblClick;
  property
OnDragDrop;
  property
OnDragOver;
  property
OnEndDrag;
  property
OnEnter;
  property
OnExit;
  property
OnMouseDown;
  property
OnMouseUp;
  property
OnMouseMove;
  property
OnResize;
end;
 
 
Here how it created:
    constructor TTrendChart.Create(AOwner:TComponent);
var
  i
:integer;
  tp
:TTrendPoints;
begin
  inherited
Create(AOwner);
 
Parent := TWinControl(AOwner);
  fCount
:= 8;
  fShowNames
:= true;
 
Caption := '';
  fMaxText
:= '100';
  fMinText
:= '0';
  fMaxTextWidth
:= Canvas.TextWidth('Bar 0');
  firstTime
:= true;
 
BevelInner := bvLowered;
  data
:= TList.Create;
 
Indexer := 0;
 
RecalcChartRect;
 
DoubleBuffered:=true;
 
for i := 0 to 10 do
 
begin
    tp
:= TTrendPoints.Create(0.0 + 0.1 * fWidth,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
    data
.Add(tp);
 
end;
 
for i := 0 to 7 do
 
begin
   
case i of
   
0: fColors[i] := clMaroon;
   
1: fColors[i] := clGreen;
   
2: fColors[i] := clOlive;
   
3: fColors[i] := clNavy;
   
4: fColors[i] := clPurple;
   
5: fColors[i] := clFuchsia;
   
6: fColors[i] := clLime;
   
7: fColors[i] := clBlue;
   
end;
    fNames
[i] := Format('Line %d',[i]);
 
end;
end;
Here is how it is painted on the Form:
    procedure TTrendChart.Paint;
var
  oldColor
:TColor;
  dataPt
:TTrendPoints;
  i
,j:integer;
  curx
:integer;
  count
,step:integer;
  r
:TRect;
begin
   inherited
Paint;

  oldcolor
:= Canvas.Pen.Color;

 
Canvas.Brush.Color:=clWhite;
  r
.Left:=chartRect.Left-25;
  r
.Right:=chartRect.Right+11;
  r
.Top:=chartRect.Top-11;
  r
.Bottom:=chartRect.Bottom+22;
 
Canvas.FillRect(r);

 
if FirstTime then
 
begin
    count
:= Indexer - 1;
 
end
 
else
    count
:= data.Count - 2;

   
{ Draw minute lines }
   
Canvas.Pen.Color := clBtnShadow;
    i
:= chartRect.left + 60;
   
while i < chartRect.Right do
   
begin
         
Canvas.Moveto(i, chartRect.top);
         
Canvas.LineTo(i, chartRect.bottom);
         i
:= i + 60;
   
end;

   
{ Draw value lines }

    step
:= (chartRect.bottom - chartRect.top) div 5;

   
if step > 0 then
   
begin
         i
:= chartRect.bottom - step;
         
while i > (chartRect.top + step - 1) do
         
begin
             
Canvas.Moveto(chartRect.left,i);
             
Canvas.LineTo(chartRect.right,i);
              i
:= i - step;
         
end;
   
end;

 
{ Draw Pens }
 
for j := 0 to fCount - 1 do
 
begin
   
Canvas.Pen.Color := fColors[j];
    dataPt
:= TTrendPoints(data.Items[0]);
   
Canvas.MoveTo(chartRect.left,PinValue(round(chartRect.bottom - (fHeight * dataPt.pnts[j] / 100.0)),
                                                                 chartRect
.top,chartRect.bottom));

   
for i := 1 to count do
   
begin
      dataPt
:= TTrendPoints(data.Items[i]);
     
if i <> Indexer then
     
begin
           
Canvas.LineTo(chartRect.left+i,PinValue(round(chartRect.bottom - (fHeight * dataPt.pnts[j] / 100.0)),
                                                               chartRect
.top,chartRect.bottom));
     
end
     
else
     
begin
           
Canvas.MoveTo(chartRect.left+i,PinValue(round(chartRect.bottom - (fHeight * dataPt.pnts[j] / 100.0)),
                                                                 chartRect
.top,chartRect.bottom));
     
end;
   
end;
 
end;

    r
:= chartRect;
   
InflateRect(r,1,1);
   
Canvas.Pen.Color := clBtnShadow;
   
Canvas.moveto(r.left,r.top);
   
Canvas.lineto(r.right,r.top);
   
Canvas.lineto(r.right,r.bottom);
   
Canvas.lineto(r.left,r.bottom);
   
Canvas.lineto(r.left,r.top);

   
{ draw index line }
//    Canvas.Pen.Color := clWhite;
   
Canvas.Pen.Color := clBlack;  
   
Canvas.MoveTo(chartRect.Left + Indexer,chartRect.top);
   
Canvas.LineTo(chartRect.left + Indexer, chartRect.bottom+1);
   
Canvas.Pen.Color := oldcolor;

   
Canvas.Font.COlor := clBlack;
   
Canvas.TextOut(chartRect.left-Canvas.TextWidth(string(fMinText))-2,chartRect.Bottom-8,string(fMinText));
   
Canvas.TextOut(chartRect.left-Canvas.TextWIdth(string(fMaxText))-2,chartRect.top-8,string(fMaxText));

   
if fShowNames then
   
begin
      curx
:= 32;
     
for i := 0 to fCount - 1 do
     
begin
       
Canvas.Font.Color := fColors[i];
       
Canvas.TextOut(curx,chartRect.bottom+4,fNames[i]);
        curx
:= curx +  fMaxTextWidth + 16;
     
end;
   
end;
end;
Here is how one would use it:
  TrendChart := TTrendChart.Create(form);
 

Any help will be appreciated. Thank you.


Answer:

ControlStyle := ControlStyle + [csOpaque];
 

Wednesday, June 29, 2011

10 things you should know about NoSQL databases

Being a software engineer myself, I found this following article quiet interesting. Read all about it - NoSQL Database!!!


NoSQL Database

BY Guy Harrison

Takeaway: The relational database model has prevailed for decades, but a new type of database — known as NoSQL — is gaining attention in the enterprise. Here’s an overview of its pros and cons.
For a quarter of a century, the relational database (RDBMS) has been the dominant model for database management. But, today, non-relational, “cloud,” or “NoSQL” databases are gaining mindshare as an alternative model for database management. In this article, we’ll look at the 10 key aspects of these non-relational NoSQL databases: the top five advantages and the top five challenges.

Five advantages of NoSQL

1: Elastic scaling

For years, database administrators have relied on scale up — buying bigger servers as database load increases — rather than scale out — distributing the database across multiple hosts as load increases. However, as transaction rates and availability requirements increase, and as databases move into the cloud or onto virtualized environments, the economic advantages of scaling out on commodity hardware become irresistible. RDBMS might not scale out easily on commodity clusters, but the new breed of NoSQL databases are designed to expand transparently to take advantage of new nodes, and they’re usually designed with low-cost commodity hardware in mind.

2: Big data

Just as transaction rates have grown out of recognition over the last decade, the volumes of data that are being stored also have increased massively. O’Reilly has cleverly called this the “industrial revolution of data.” RDBMS capacity has been growing to match these increases, but as with transaction rates, the constraints of data volumes that can be practically managed by a single RDBMS are becoming intolerable for some enterprises. Today, the volumes of “big data” that can be handled by NoSQL systems, such as Hadoop, outstrip what can be handled by the biggest RDBMS.

3: Goodbye DBAs (see you later?)

Despite the many manageability improvements claimed by RDBMS vendors over the years, high-end RDBMS systems can be maintained only with the assistance of expensive, highly trained DBAs. DBAs are intimately involved in the design, installation, and ongoing tuning of high-end RDBMS systems. NoSQL databases are generally designed from the ground up to require less management:  automatic repair, data distribution, and simpler data models lead to lower administration and tuning requirements — in theory. In practice, it’s likely that rumors of the DBA’s death have been slightly exaggerated. Someone will always be accountable for the performance and availability of any mission-critical data store.

4: Economics

NoSQL databases typically use clusters of cheap commodity servers to manage the exploding data and transaction volumes, while RDBMS tends to rely on expensive proprietary servers and storage systems. The result is that the cost per gigabyte or transaction/second for NoSQL can be many times less than the cost for RDBMS, allowing you to store and process more data at a much lower price point.

5: Flexible data models

Change management is a big headache for large production RDBMS. Even minor changes to the data model of an RDBMS have to be carefully managed and may necessitate downtime or reduced service levels. NoSQL databases have far more relaxed — or even nonexistent — data model restrictions. NoSQL Key Value stores and document databases allow the application to store virtually any structure it wants in a data element. Even the more rigidly defined BigTable-based NoSQL databases (Cassandra, HBase) typically allow new columns to be created without too much fuss.
The result is that application changes and database schema changes do not have to be managed as one complicated change unit. In theory, this will allow applications to iterate faster, though,clearly, there can be undesirable side effects if the application fails to manage data integrity.

Five challenges of NoSQL

The promise of the NoSQL database has generated a lot of enthusiasm, but there are many obstacles to overcome before they can appeal to mainstream enterprises. Here are a few of the top challenges.

1: Maturity

RDBMS systems have been around for a long time. NoSQL advocates will argue that their advancing age is a sign of their obsolescence, but for most CIOs, the maturity of the RDBMS is reassuring. For the most part, RDBMS systems are stable and richly functional. In comparison, most NoSQL alternatives are in pre-production versions with many key features yet to be implemented. Living on the technological leading edge is an exciting prospect for many developers, but enterprises should approach it with extreme caution.

2: Support

Enterprises want the reassurance that if a key system fails, they will be able to get timely and competent support. All RDBMS vendors go to great lengths to provide a high level of enterprise support. In contrast, most NoSQL systems are open source projects, and although there are usually one or more firms offering support for each NoSQL database, these companies often are small start-ups without the global reach, support resources, or credibility of an Oracle, Microsoft, or IBM.

3: Analytics and business intelligence

NoSQL databases have evolved to meet the scaling demands of modern Web 2.0 applications. Consequently, most of their feature set is oriented toward the demands of these applications. However, data in an application has value to the business that goes beyond the insert-read-update-delete cycle of a typical Web application. Businesses mine information in corporate databases to improve their efficiency and competitiveness, and business intelligence (BI) is a key IT issue for all medium to large companies. NoSQL databases offer few facilities for ad-hoc query and analysis. Even a simple query requires significant programming expertise, and commonly used BI tools do not provide connectivity to NoSQL.
Some relief is provided by the emergence of solutions such as HIVE or PIG, which can provide easier access to data held in Hadoop clusters and perhaps eventually, other NoSQL databases. Quest Software has developed a product — Toad for Cloud Databases — that can provide ad-hoc query capabilities to a variety of NoSQL databases.

4: Administration

The design goals for NoSQL may be to provide a zero-admin solution, but the current reality falls well short of that goal. NoSQL today requires a lot of skill to install and a lot of effort to maintain.

5: Expertise

There are literally millions of developers throughout the world, and in every business segment, who are familiar with RDBMS concepts and programming. In contrast, almost every NoSQL developer is in a learning mode. This situation will address naturally over time, but for now, it’s far easier to find experienced RDBMS programmers or administrators than a NoSQL expert.

Conclusion

NoSQL databases are becoming an increasingly important part of the database landscape, and when used appropriately, can offer real benefits. However, enterprises should proceed with caution with full awareness of the legitimate limitations and issues that are associated with these databases.

About the author

Guy Harrison is the director of research and development at Quest Software. A recognized database expert with more than 20 years of experience in application and database administration, performance tuning, and software development, Guy is the author of several books and many articles on database technologies and a regular speaker at technical conferences.