I just noticed a nice video by Bob Swart from CodeRage III. He has several demos in Delphi and Delphi Prism that he goes through in the 45 minute video:
Using RemObjects SDK and Hydra for Cross-platform Multi-tier Delphi Applications
If you're looking for an visual introduction to RemObjects SDK and RemObjects Hydra this is a nice one. He goes through how to create a basic RO SDK server and client. Then he creates the two samples using Hydra. In is a .NET Hydra host application running an unmanaged Delphi Hydra plugin (which uses the RO SDK service he had done previously) and a Delphi Hydra host application running a managed Prism .NET Hydra plugin. Very slick and demonstrates how effective Hydra can be for Delphi developers who have one foot in the native Delphi world and one foot in the .NET world. No use in rewriting existing, working code from one language to another. Just use Hydra!
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Sunday, July 19, 2009
Saturday, July 18, 2009
Languages and Splitting the Interface from Implementation
Hopefully a rare event, but I need to rant a little. After looking through C# code that isn't my own today I'm longing for a language that splits the interface from the implementation details. It isn't that the code is bad, it's that there's a good bit of it and I'm not used to working in a language that doesn't split the interface from the implementation. I'm far more comfortable looking through Pascal Interface and Implementation sections and Objective-C/C/C++ header files and implementation files. Lately I've seen a lot of criticism of that as "old" because newer languages don't use it at all, but I have to say when you come to a significant amount of code you didn't write from a person whose style you're not familiar with, it helps. I'll have to reinstall ModelMaker Code Explorer. For some reason it's not available in Vistual Studio any longer. I must have removed it at some point, but this is killing me and turning on code folding isn't helping... In fact, perhaps I'll just import everything into ModelMaker itself. Perhaps people feel separate interface sections are redundant because they use UML tools like that instead. Don't know, but it's very similar I suppose. I've come to like C#, I really have. Coming from Delphi it feels very natural, particularly since the same man had a heavy hand in both. But I really miss interface sections and header files when I work in it. Okay, I think I'm done ranting now...
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Thursday, July 16, 2009
Part 2: ROSessionsClient Sample in RO SDK for OS X
In Part 1 we looked at how to create an OS X client using the RemObjects SDK for OS X to talk to our RemObjects SDK for .NET Sessions server. In this article we're going to implement two of the four methods that are defined in that server.
First we'll define our two methods in the header. It's simple of course, and looks like this:
After they finished the beta and I saw their changes I was thrilled to learn about NSBeginAlertSheet from his changes to my code here. Yes, I'm that new to Cocoa development. ;-) We can also see how the RemObjects team used BOOL loggedIn to improve my original code for getting our ClientID and SessionID from the server. The code and comments should make the performLogin code self-explanatory. First we must assign clientChannel the server's URL and then we can login using our loginService. Since I created this sample to be as simple as possible (I was just learning) I didn't use their other method of service discover. I could have used ROZeroConf which is based on Apple's Bonjour protocol for automatic service discovery. If you implement that in your server then what I did here wouldn't have been necessary. All that would have been taken care of in your initialization code.
Let's look at the loginService a little more closely. Where is it defined? When we initialized the service in Part 1 the code looked like this:
Where is LoginService_Proxy defined? It is of the type ROProxy and implements an ILoginService protocol. Both were automatically generated for us in the Sessions_Library_Intf.h header file that was created from our server's RODL file when we ran the rodl2objc tool. The ILoginService protocol is very simple and really defines everything we need:
And the LoginService_Proxy that was generated looks like this:
We can now login to our Sessions server and we also have a little more understanding of the proxies that were created with the rodl2objc tool. When we start the ROSessionsClient application we can see our ClientID is created and once we login we can now see the SessionID as well and our Logout button is enabled. So far so good!

The .NET server shows that the service is created and shows the SessionID that was created. Naturally it's the same as the SessionID we see in the client:

Now all we have to do is implement performLogout and we're good to go. We've already seen the definitions of the Logout method in the LoginService_Proxy code above. This is a simple one line affair with some other cosmetic things for the UI. We just call the Logout method of the loginService and send it our ClientID so the server can log us out properly.
In Part 1 we got the project started and did some initialization code. Here in Part 2 we implemented both the Login and Logout methods of our server's LoginService. In Part 3 we'll take a look at how we can set session variables and retrieve them at a later time using the two methods of the server's SessionService.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
- performLogin
- performLogout
First we'll define our two methods in the header. It's simple of course, and looks like this:
#import <Cocoa/Cocoa.h>
#import <RemObjectsSDK/RemObjectsSDK.h>
#import "Sessions_Library_Intf.h"
@interface ROSessionsClient : NSObject
{
//see Part 1 for this section's contents
}
#pragma mark loginService methods
-(IBAction)performLogin:(id)sender;
-(IBAction)performLogout:(id)sender;
@end
After they finished the beta and I saw their changes I was thrilled to learn about NSBeginAlertSheet from his changes to my code here. Yes, I'm that new to Cocoa development. ;-) We can also see how the RemObjects team used BOOL loggedIn to improve my original code for getting our ClientID and SessionID from the server. The code and comments should make the performLogin code self-explanatory. First we must assign clientChannel the server's URL and then we can login using our loginService. Since I created this sample to be as simple as possible (I was just learning) I didn't use their other method of service discover. I could have used ROZeroConf which is based on Apple's Bonjour protocol for automatic service discovery. If you implement that in your server then what I did here wouldn't have been necessary. All that would have been taken care of in your initialization code.
#pragma mark loginService methods
-(IBAction)performLogin:(id)sender
{
[lblClientID setStringValue:myClientID];
@try
{
//Set the clientChannel to the correct URL for our server
[clientChannel setTargetUrl:[edtServerURL stringValue]];
//Call the loginService
loggedIn = [loginService Login:[edtUsername stringValue] :[edtPassword stringValue]];
if (loggedIn)
{
NSLog(@"logged in");
[lblLoggedIn setStringValue:(NSString *)@"Logged in"];
[btnLogout setEnabled:YES];
[btnSetValue setEnabled:YES];
mySessionID = @"";
mySessionID = [[sessionService GetSessionID] uppercaseString];
[lblSessionID setStringValue:mySessionID];
NSLog(@"%@", mySessionID);
}
else
{
NSLog(@"login failed");
NSBeginAlertSheet(@"Not logged in", nil, nil, nil, [NSApp mainWindow],
nil, nil, nil, nil, @"Login failed");
}
}
@catch(id exception)
{
NSLog([exception reason]);
[self ShowException:[exception reason]];
}
}
Let's look at the loginService a little more closely. Where is it defined? When we initialized the service in Part 1 the code looked like this:
loginService = [[LoginService_Proxy alloc] initWithMessage:message channel:clientChannel];
Where is LoginService_Proxy defined? It is of the type ROProxy and implements an ILoginService protocol. Both were automatically generated for us in the Sessions_Library_Intf.h header file that was created from our server's RODL file when we ran the rodl2objc tool. The ILoginService protocol is very simple and really defines everything we need:
@protocol ILoginService
- (BOOL) Login
:(NSString*) UserID
:(NSString*) Password
;
- (void) Logout
:(NSString*) SessionID
;
@end
And the LoginService_Proxy that was generated looks like this:
@interface LoginService_Proxy : ROProxy <ILoginService>
{
}
-(id) initWithMessage:(ROMessage*) aMessage channel:(ROClientChannel*) aChannel;
-(void) dealloc;
-(NSString*) __getInterfaceName;
- (BOOL) Login
:(NSString*) UserID
:(NSString*) Password
;
- (void) Logout
:(NSString*) SessionID
;
@end
We can now login to our Sessions server and we also have a little more understanding of the proxies that were created with the rodl2objc tool. When we start the ROSessionsClient application we can see our ClientID is created and once we login we can now see the SessionID as well and our Logout button is enabled. So far so good!

The .NET server shows that the service is created and shows the SessionID that was created. Naturally it's the same as the SessionID we see in the client:

Now all we have to do is implement performLogout and we're good to go. We've already seen the definitions of the Logout method in the LoginService_Proxy code above. This is a simple one line affair with some other cosmetic things for the UI. We just call the Logout method of the loginService and send it our ClientID so the server can log us out properly.
-(IBAction)performLogout:(id)sender
{
@try
{
[loginService Logout:myClientID];
loggedIn = NO;
[lblLoggedIn setStringValue:(NSString *)@"Not logged in"];
mySessionID = @"";
[lblSessionID setStringValue:mySessionID];
[btnLogout setEnabled:NO];
[btnSetValue setEnabled:NO];
[btnGetValue setEnabled:NO];
[edtValue setStringValue:@""];
[edtName setStringValue:@""];
NSLog(@"Logged out");
}
@catch(id exception)
{
NSLog([exception reason]);
[self ShowException:[exception reason]];
}
}
In Part 1 we got the project started and did some initialization code. Here in Part 2 we implemented both the Login and Logout methods of our server's LoginService. In Part 3 we'll take a look at how we can set session variables and retrieve them at a later time using the two methods of the server's SessionService.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Part 1: ROSessionsClient Sample in RO SDK for OS X
Back when RemObjects had RemObjects SDK for OS X in beta of course there weren't many samples yet. I looked through the existing .NET and Delphi RemObjects SDK samples to figure out someplace to start and decided on the .NET Sessions sample project. I was just learning Cocoa development so it had to be simple! I was reading the newly released third edition of Aaron Hillegass book Cocoa Programming for Mac OS X at the time. The .NET Session sample project was just what the doctor ordered! All I needed to do was login and then set and retrieve some key value pairs on the server. In this article we'll go through how I created the project and do some simple init and dealloc code for the RemObjects services to get things started.
In XCode I created a new project entitled "ROSessionsClient". I opened the MainMenu.nib file (which appears to have been converted to a .xib file now) and created my UI. My original UI was pretty close to what you would see today if you get the RemObjects SDK, but they did clean it up a touch. Here's what it looks like right now:

Since I'm using VMWare Fusion for Windows Development on OS X I copied the RODL file from the .NET Sessions sample folder to a folder in OS X and ran the RemObjects rodl2objc tool. That tool takes the RODL file and creates the proxies files we need to talk to our RemObjects server. I saved the Sessions_Library_Intf.h and Sessions_Library_Inft.m files to the ROSessionsClient it created to my ROSessionsClient folder. From there I went into XCode, right-clicked on "Classes" and selected the "Add" and then "Existing Files.... Once they were included in my project I was ready to get started in Interface Builder and XCode.
In my ROSessionsClient.h header file I added the necessary NSButton, NSTextField IBOutlets that were needed and wired them up in Interface Builder. I won't go into the details of how to do that since it's outside the scope of this article. We only needed a few methods since this is a pretty simple program. Once I was done the ROSessionsClient.h header file looked pretty close to the code below, the only real changes being the addition of BOOL loggedIn:
The initialization code is really, really easy. You simply create your ROBinMessage and ROHttpClientChannel and then create the loginService and sessionService with them. The loginService and the sessionService are defined in the Sessions_Library_Intf files we created earlier using the rodl2objc tool. So our init method looks like this:
Naturally, the dealloc code is even simpler:
We've done quite a bit so far. Now that the basics are in place we can use the services we created to access some methods on the Sessions server. In Part 2 we're going to implement two of the server's methods, login and logout.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
In XCode I created a new project entitled "ROSessionsClient". I opened the MainMenu.nib file (which appears to have been converted to a .xib file now) and created my UI. My original UI was pretty close to what you would see today if you get the RemObjects SDK, but they did clean it up a touch. Here's what it looks like right now:

Since I'm using VMWare Fusion for Windows Development on OS X I copied the RODL file from the .NET Sessions sample folder to a folder in OS X and ran the RemObjects rodl2objc tool. That tool takes the RODL file and creates the proxies files we need to talk to our RemObjects server. I saved the Sessions_Library_Intf.h and Sessions_Library_Inft.m files to the ROSessionsClient it created to my ROSessionsClient folder. From there I went into XCode, right-clicked on "Classes" and selected the "Add" and then "Existing Files.... Once they were included in my project I was ready to get started in Interface Builder and XCode.
In my ROSessionsClient.h header file I added the necessary NSButton, NSTextField IBOutlets that were needed and wired them up in Interface Builder. I won't go into the details of how to do that since it's outside the scope of this article. We only needed a few methods since this is a pretty simple program. Once I was done the ROSessionsClient.h header file looked pretty close to the code below, the only real changes being the addition of BOOL loggedIn:
#import <Cocoa/Cocoa.h>
#import <RemObjectsSDK/RemObjectsSDK.h>
#import "Sessions_Library_Intf.h"
@interface ROSessionsClient : NSObject
{
IBOutlet NSTextField *edtServerURL;
IBOutlet NSTextField *lblSessionID;
IBOutlet NSTextField *lblClientID;
IBOutlet NSTextField *edtUsername;
IBOutlet NSTextField *edtPassword;
IBOutlet NSButton *btnLogin;
IBOutlet NSButton *btnLogout;
IBOutlet NSTextField *lblLoggedIn;
BOOL loggedIn;
IBOutlet NSTextField *edtName;
IBOutlet NSTextField *edtValue;
IBOutlet NSButton *btnGetValue;
IBOutlet NSButton *btnSetValue;
LoginService_Proxy *loginService;
SessionService_Proxy *sessionService;
ROBinMessage *message;
ROHTTPClientChannel *clientChannel;
NSString *myClientID;
NSString *mySessionID;
}
@end
The initialization code is really, really easy. You simply create your ROBinMessage and ROHttpClientChannel and then create the loginService and sessionService with them. The loginService and the sessionService are defined in the Sessions_Library_Intf files we created earlier using the rodl2objc tool. So our init method looks like this:
#pragma mark init/dealloc
- (id)init
{
self = [super init];
if (self)
{
InitializeSessions_Library();
message = [[ROBinMessage alloc] init];
[message setUseCompression:NO];
clientChannel = [[ROHTTPClientChannel alloc] init];
loginService = [[LoginService_Proxy alloc] initWithMessage:message channel:clientChannel];
sessionService = [[SessionService_Proxy alloc] initWithMessage:message channel:clientChannel];
//get the message clientID and turn it into a string we can display on the form.
myClientID = [[[message clientID] stringValue] retain];
NSLog(@"myClientID is %@", myClientID);
}
return self;
}
Naturally, the dealloc code is even simpler:
- (void)dealloc
{
[message release];
[clientChannel release];
[loginService release];
[sessionService release];
[myClientID release];
[super dealloc];
}
We've done quite a bit so far. Now that the basics are in place we can use the services we created to access some methods on the Sessions server. In Part 2 we're going to implement two of the server's methods, login and logout.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
RemObjects DataAbstract for OS X beta drop
A new beta has been announced for RemObjects DataAbstract for OS X. marc hoffman has blogged its progress lately and I just downloaded the update. Looking forward to checking it out. I'll be doing some blogging on it soon. I've been more focused on Windows work lately, but my heart is still longing to do much more Mac OS X development. I think I'll start with one of their RemObjects SDK for OS X samples that I wrote when it was in beta. They did some nice updates to my original, but it's pretty straightforward and gives some nice insight into how their products work.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Labels:
DataAbstract,
OS X Development,
RemObjects
Monday, July 13, 2009
Great Article Using DataAbstract with Hydra
Nathanial Woolls has written a great article on combining RemObject DataAbstract and Hydra in a Delphi project in his blog. A must read for anyone interested in doing it I think:
Creating a DataAbstract Server Utilizing Hydra Plugins
I haven't used Hydra yet myself, so I found it pretty interesting. Hopefully one of these days the RemObjects team will make a wizard for this sort of project to cut down a little of the customization that needs to be done. Not bad, though, and the combo clearly makes for a much more flexible DataAbstract server.
Nathaniel also wrote a pretty in depth article on developing Hydra packages in Delphi here:
Creating Custom Packages for Hydra
I've always found these plugin architectures interesting, just haven't used one yet. If it's possible to create a single .exe for a Delphi project, I will. It's just so much simpler and I'm a "simple" kind of guy. :-) If I ever do it, though, I'll definitely come back and consult these articles first.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Creating a DataAbstract Server Utilizing Hydra Plugins
I haven't used Hydra yet myself, so I found it pretty interesting. Hopefully one of these days the RemObjects team will make a wizard for this sort of project to cut down a little of the customization that needs to be done. Not bad, though, and the combo clearly makes for a much more flexible DataAbstract server.
Nathaniel also wrote a pretty in depth article on developing Hydra packages in Delphi here:
Creating Custom Packages for Hydra
I've always found these plugin architectures interesting, just haven't used one yet. If it's possible to create a single .exe for a Delphi project, I will. It's just so much simpler and I'm a "simple" kind of guy. :-) If I ever do it, though, I'll definitely come back and consult these articles first.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Labels:
DataAbstract,
Delphi,
Hydra,
RemObjects
Thursday, July 9, 2009
Is Google's Chrome OS Really a Threat?
An article on Macworld entitled Google OS may force Microsoft to reinvent Windows has a couple interesting quotes in it in addition to it's provacative title.
“Google Chrome OS is the death knell for a PC-centric OS,” Gillett said. “The next versions of Windows need to be much more Internet-centric.”
"Google’s OS challenge will certainly accelerate the move to a world where applications are no longer dependent on an operating system"
As I see it the article raises three questions.
To the first question, how does an operating system whose centerpiece is web browser and using apps through that browser pose a threat to Microsoft, or Apple and Linux for that matter? Do they lack browsers? It doesn't appear so. I have three installed on my MacBook Pro alone. I can develop apps that work on each of them without any problem. So with Windows, OS X or Linux I can have a browser application work great. I can also create rich, visually complex applications for them using mature, well documented API's. I would lose that with Google's OS. From what I've read their windowing system is a light, brand new system. They expect pretty much everything to be done over the browser. That's not good enough. Never has been, never will be.
Case in point. When Apple released the first iPhone it was great, but they said you could only create browser applications for it. Developers were very disappointed even though they loved the device. They knew what they could do if they had an iPhone SDK to write native apps. Eventually Apple provided an iPhone SDK and when they displayed the applications being developed at the next WWDC it was simply amazing. Anyone who claims browser apps are all you need must justify that statement in the face of the runaway success of the Apple AppStore after the iPhone SDK was released.
Now to the second point. What exactly is a "PC-centric OS"? I have all the things I need to develop for Windows Mobile using the .NET compact framework on my laptop right now. Those apps will work on any number of devices running Windows Mobile on the market today. They're losing marketshare badly to Apple's iPhone, Research in Motion's Blackberry and now the Palm Pre, but that's irrelevant to the discussion. They do have products to meet this market now, they just need to improve their product offering. I've played with Windows based netbooks at the stores (I personally have no need for one) and they seem to be fine. Of course Microsoft can work on optimizing performance for them, but they'll also get more and more horsepower as time goes on. Their specs are already far better than the first servers I ever worked on when I was getting started in the business!
The third point has been debated in the industry ever since Netscape first started to openly challenge Microsoft on this front in the early 90's. I hate to surprise the person who made the quote, but any company that creates a web based application that only works on Internet Explorer is taking a risk with their business right now. This is a present reality. Certainly there are many companies out there whose web applications only work in Internet Explorer, but this has been becoming more and more rare for quite awhile. The 90's browser wars are over in the sense of competing proprietary DHTML API's being developed. The new browser wars are based on standards compliance, features, ease of use, speed, etc.
On a lighter note, I've also seen many people openly wonder if they'll be sued for tying their web browser to the OS like Microsoft was. Oops, did I reveal my opinion of that particular lawsuit? Well, let the lawsuits begin. I hear Google is flush with cash after all...
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
“Google Chrome OS is the death knell for a PC-centric OS,” Gillett said. “The next versions of Windows need to be much more Internet-centric.”
"Google’s OS challenge will certainly accelerate the move to a world where applications are no longer dependent on an operating system"
As I see it the article raises three questions.
- Does Google OS really mean Microsoft needs to "reinvent Windows"?
- Is Google Chrome OS really "the death knell for a PC-centric OS"?
- Will Google's OS push the world more towards web apps that are independent of the OS?
To the first question, how does an operating system whose centerpiece is web browser and using apps through that browser pose a threat to Microsoft, or Apple and Linux for that matter? Do they lack browsers? It doesn't appear so. I have three installed on my MacBook Pro alone. I can develop apps that work on each of them without any problem. So with Windows, OS X or Linux I can have a browser application work great. I can also create rich, visually complex applications for them using mature, well documented API's. I would lose that with Google's OS. From what I've read their windowing system is a light, brand new system. They expect pretty much everything to be done over the browser. That's not good enough. Never has been, never will be.
Case in point. When Apple released the first iPhone it was great, but they said you could only create browser applications for it. Developers were very disappointed even though they loved the device. They knew what they could do if they had an iPhone SDK to write native apps. Eventually Apple provided an iPhone SDK and when they displayed the applications being developed at the next WWDC it was simply amazing. Anyone who claims browser apps are all you need must justify that statement in the face of the runaway success of the Apple AppStore after the iPhone SDK was released.
Now to the second point. What exactly is a "PC-centric OS"? I have all the things I need to develop for Windows Mobile using the .NET compact framework on my laptop right now. Those apps will work on any number of devices running Windows Mobile on the market today. They're losing marketshare badly to Apple's iPhone, Research in Motion's Blackberry and now the Palm Pre, but that's irrelevant to the discussion. They do have products to meet this market now, they just need to improve their product offering. I've played with Windows based netbooks at the stores (I personally have no need for one) and they seem to be fine. Of course Microsoft can work on optimizing performance for them, but they'll also get more and more horsepower as time goes on. Their specs are already far better than the first servers I ever worked on when I was getting started in the business!
The third point has been debated in the industry ever since Netscape first started to openly challenge Microsoft on this front in the early 90's. I hate to surprise the person who made the quote, but any company that creates a web based application that only works on Internet Explorer is taking a risk with their business right now. This is a present reality. Certainly there are many companies out there whose web applications only work in Internet Explorer, but this has been becoming more and more rare for quite awhile. The 90's browser wars are over in the sense of competing proprietary DHTML API's being developed. The new browser wars are based on standards compliance, features, ease of use, speed, etc.
On a lighter note, I've also seen many people openly wonder if they'll be sued for tying their web browser to the OS like Microsoft was. Oops, did I reveal my opinion of that particular lawsuit? Well, let the lawsuits begin. I hear Google is flush with cash after all...
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Wednesday, July 8, 2009
Creating a WPF DALinq Client App
Since RemObjects DataAbstract for .NET doesn't have a wizard like it does for WinForms projects yet you have to do a few extra steps yourself. I started with the DALinq project that I'd been working on in recent blog posts and simply added a new WPF project to the solution. I named the project WPFLinqClient and after the new project is created we're only a few steps away.
The steps look like more effort than they really are. Particularly once you get comfortable with the framework. Since I'm still somewhat new to WPF that's where I spent most of my time learning new things. In the end we have a nice little form that opens our LINQ query and updates it for us automagically. The end result looks like this:

This test project can be downloaded here.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
- Add a new Component Class to the project using the Add New Item wizard and name it something, I named mine "DataService"
- Open the DataService component in the designer and add a BinMessage, a LinqRemoteDataAdapter, a client channel (ipHttpClientChannel in my case), Bin2DataStreamer and a RemoteService on the designer surface and wire them appropriately
- Since this is a simple exercise I made the Modifier for the LinqRemoteDataAdapter on the DataService component public so I could access it easily. For a larger project you'll probably want to do this in a more OOP manner.
- Select the LinqRemoteDataAdapter's Smart Tag and chose the "Create DA LINQ Classes" option. Be sure to have your server running when you run the wizard or you'll get an error because it can't connect. Afterwards you should have a TableDefinitions.cs file automatically added to the WPF client's project.  

- Right click on your WPF project and use the Add Existing Item wizard to insert a shortcut to the DataAbstract Server's _Intf file. Be sure to use the drop down menu and select "Add As Link".

- Add a DataGrid and a couple buttons to the main Window. One button will be for opening the query and one for updating the query after any changes you make using DALinq DataBinding.
- Add a couple variables to use and instantiate our DataService so we can get the data like this:
private IQueryable<Customers> _list;
private DataService _dataService;
public Window1()
{
InitializeComponent();
_dataService = new DataService();
} - Add the following code behind our query button:
private void btnOpenQuery_Click(object sender, RoutedEventArgs e)
{
_list = from cust in _data.linqRemoteDataAdapter.GetTable<Customers>()
where (cust.City == "México D.F.")
orderby cust.ContactName ascending
select cust;
dataGrid1.AutoGenerateColumns = true;
dataGrid1.ItemsSource = null;
dataGrid1.ItemsSource = _list.ToDABindingList();
} - We'll add this DALinq DataBinding code behind our update button:
private void btnUpdate_Click(object sender, RoutedEventArgs e)
{
((DABindingList<Customers>)dataGrid1.ItemsSource).SaveChanges(_dataService.linqRemoteDataAdapter);
_dataService.linqRemoteDataAdapter.ApplyChanges();
}
The steps look like more effort than they really are. Particularly once you get comfortable with the framework. Since I'm still somewhat new to WPF that's where I spent most of my time learning new things. In the end we have a nice little form that opens our LINQ query and updates it for us automagically. The end result looks like this:

This test project can be downloaded here.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Labels:
DALinq,
DataAbstract,
LINQ,
RemObjects,
WPF
DALinq databinding
Databinding in WinForms applications with RemObjects DataAbstract's DALinq is pretty straightforward. For this example I created a standard WinForms DataAbstract project and pointed it to the Northwind database I have in SQL Server. I removed the standard RemoteDataAdapter and replaced it with the LinqRemoteDataAdapter from the Visual Studio 2008 toolbox. I then clicked on the LinqRemoteDataAdapter's Smart Tag so I could create my LINQ classes:

In this exercise I'll create two buttons. One to open the query and one to update any changes I make to a field. The code for the query will be similar to the code I used in a previous blog post, but not quite the same. We'll come back to that later.
And the code that we'll run after changing a field in the grid is equally straightforward:
Easy! the only problem I had was I originally only selected a few fields from the table. That query would have been written like this:
As you can see I used a parameterized select statement to get just the fields I wanted from the table. Unfortunately to use the _list.ToDABindingList(); method you must have a parameterless select statement. That means all the fields are brought over. This isn't as efficient in a WinForms application using the standard DataAbstract RemoteDataAdapter and DataSets. That method is much more efficient because you have complete control over what fields are brought across the wire. It will also only update the change deltas for the updates for your updates. I've asked support if there's any way around this, or if they plan on adding the option to use parameterized select statements in the future. If they do, then DALinq databinding would be just as nice to use as the standard RemoteDataAdapter using DataSets.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.

In this exercise I'll create two buttons. One to open the query and one to update any changes I make to a field. The code for the query will be similar to the code I used in a previous blog post, but not quite the same. We'll come back to that later.
private void btnOpenQuery_Click(object sender, EventArgs e)
{
_list = from cust in linqRemoteDataAdapter.GetTable<Customers>()
where (cust.City == "México D.F.")
orderby cust.CompanyName ascending
select cust;
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = null;
dataGridView1.DataSource = _list.ToDABindingList();
}
And the code that we'll run after changing a field in the grid is equally straightforward:
private void btnUpdate_Click(object sender, EventArgs e)
{
((DABindingList<Customers>)dataGridView1.DataSource).SaveChanges(linqRemoteDataAdapter);
linqRemoteDataAdapter.ApplyChanges();
}
Easy! the only problem I had was I originally only selected a few fields from the table. That query would have been written like this:
_list = from cust in linqRemoteDataAdapter.GetTable()
where (cust.City == "México D.F.")
orderby cust.CompanyName ascending
select new { cust.CustomerID, cust.ContactName, cust.Address, cust.City };
As you can see I used a parameterized select statement to get just the fields I wanted from the table. Unfortunately to use the _list.ToDABindingList(); method you must have a parameterless select statement. That means all the fields are brought over. This isn't as efficient in a WinForms application using the standard DataAbstract RemoteDataAdapter and DataSets. That method is much more efficient because you have complete control over what fields are brought across the wire. It will also only update the change deltas for the updates for your updates. I've asked support if there's any way around this, or if they plan on adding the option to use parameterized select statements in the future. If they do, then DALinq databinding would be just as nice to use as the standard RemoteDataAdapter using DataSets.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Labels:
DALinq,
DataAbstract,
LINQ,
RemObjects
Great MSDN Page "101 LINQ Samples"
I've been playing with LINQ a lot today and found this handy page. Great for people just getting into it like me:
101 LINQ Samples
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him on his blogs and his LinkedIn profile is here.
101 LINQ Samples
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him on his blogs and his LinkedIn profile is here.
RemoteTable and DALinq
In my last blog post on DALinq I was trying to figure out how I could have my query be more natural looking. The GetTable method simply looked out of place. I've gotten used to it, but think I see how to get around it now after looking at how LINQ to SQL works. The linqRemoteDataAdapter.GetTable<T>() method returns the type RemoteTable<T>. Simply assign it to a variable and use that variable from then on if you like:
Or if you prefer dot notation:
So if you're using DALinq in RemObjects DataAbstract for your n-tier framework you can use either the GetTable syntax or create a variable and do it more like the books present examples with LINQ to Objects.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
RemoteTable<Customers> OurCustomers = linqRemoteDataAdapter.GetTable<Customers>();
var aList = from cust in OurCustomers
where (cust.City == "México D.F.")
orderby cust.ContactName ascending
select new { cust.CustomerID, cust.ContactName, cust.Address, cust.City };
Or if you prefer dot notation:
RemoteTable<Customers> OurCustomers = linqRemoteDataAdapter.GetTable<Customers>();
var aList = OurCustomers
.Where(cust => cust.City == "México D.F.")
.OrderBy(cust => cust.ContactName)
.Select(cust =>
new { cust.CustomerID, cust.ContactName, cust.Address, cust.City });
So if you're using DALinq in RemObjects DataAbstract for your n-tier framework you can use either the GetTable syntax or create a variable and do it more like the books present examples with LINQ to Objects.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Labels:
DALinq,
DataAbstract,
LINQ,
RemObjects
Tuesday, July 7, 2009
RemObjects DataAbstract DALinq
I went to the local library yesterday to see if they had a book on Windows Presentation Foundation (yes, I'm that cheap). They didn't have one, but did have a book on LINQ which I've been meaning to look into more. Since I use RemObjects DataAbstract I was very interested in playing with their DALinq features. All I have to do is write the LINQ query and the SQL will get generated on the server for me sending back the correct data. So let's get started with the project.
I ran through the standard C# WinForms DataAbstract project and pointed it at the Northwind database in my SQL Server 2005 install. After going through the wizard my first step was to figure out why I didn't have a LinqRemoteDataAdapter in my Visual Studio 2008 toolbox. Well, before you start a DALinq project make sure you don't have it set up to create a .NET 2.0 compatible project (which is what I normally create). I set the project options for my client to .NET 3.5 and got to work.
First I removed the standard RemoteDataAdapter and replaced it with the LinqRemoteDataAdapter. Then I selected the LinqRemoteAdapter's Smart Tag and selected "Create DA LINQ Classes" from the menu.

I then added System.Linq and RemObjects.DataAbstract.Linq to the using clauses. Okay, perhaps I did this after my linq query got errors and Google reminded me that the using clauses are important. ;-) My Linq query was pretty simple for this sample and was just put behind a button that made the query and then displayed it in a DataGridView. It was based on the query on the feature's webpage
Or, if you prefer dot notation:
I did have to adjust the original query which was taken almost directly from the webpage and looked like this:
When I create it like that I got a squiggly line under "Customers" that says "Could not find an implementation of the query pattern for source type 'DALinqClient.Customers'. 'Where' not found." When I consulted the sample DALinq project that ships with the project I changed the code to use the GetTable command they used and it worked great!

As I learn more about Silverlight I'm looking forward to being able to use this feature for my data access. At least with Silverlight 2 (I haven't kept up much with v3) this will make data access MUCH easier. The project (as simple as it is) can be found here.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
I ran through the standard C# WinForms DataAbstract project and pointed it at the Northwind database in my SQL Server 2005 install. After going through the wizard my first step was to figure out why I didn't have a LinqRemoteDataAdapter in my Visual Studio 2008 toolbox. Well, before you start a DALinq project make sure you don't have it set up to create a .NET 2.0 compatible project (which is what I normally create). I set the project options for my client to .NET 3.5 and got to work.
First I removed the standard RemoteDataAdapter and replaced it with the LinqRemoteDataAdapter. Then I selected the LinqRemoteAdapter's Smart Tag and selected "Create DA LINQ Classes" from the menu.

I then added System.Linq and RemObjects.DataAbstract.Linq to the using clauses. Okay, perhaps I did this after my linq query got errors and Google reminded me that the using clauses are important. ;-) My Linq query was pretty simple for this sample and was just put behind a button that made the query and then displayed it in a DataGridView. It was based on the query on the feature's webpage
var aList = from c in linqRemoteDataAdapter.GetTable<Customers>()
where (c.City == "México D.F.")
select new { c.CustomerID, c.ContactName, c.Address };
dataGridView1.AutoGenerateColumns = true;
bindingSource1.DataSource = aList;
Or, if you prefer dot notation:
var aList = linqRemoteDataAdapter.GetTable<Customers>()
.Where(c => c.City == "México D.F.")
.Select(c => new { c.CustomerID, c.ContactName, c.Address });
I did have to adjust the original query which was taken almost directly from the webpage and looked like this:
var aList = from c in Customers
where (c.City == "México D.F.")
select new { c.CustomerID, c.ContactName, c.Address };
When I create it like that I got a squiggly line under "Customers" that says "Could not find an implementation of the query pattern for source type 'DALinqClient.Customers'. 'Where' not found." When I consulted the sample DALinq project that ships with the project I changed the code to use the GetTable command they used and it worked great!

As I learn more about Silverlight I'm looking forward to being able to use this feature for my data access. At least with Silverlight 2 (I haven't kept up much with v3) this will make data access MUCH easier. The project (as simple as it is) can be found here.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Labels:
DALinq,
DataAbstract,
LINQ,
RemObjects
Monday, July 6, 2009
Scrolling a TextBlock in WPF
One requirement for a project I've been working on is to scroll text across the screen. I've been playing around with WPF to see if that's the way I should go. Seems to be pretty easy to get the text to scroll, but I haven't been too pleased with it so far. Periodically there's just a touch of choppiness as the text scrolls by. Not bad, but I really need it to be as reliably smooth as possible. I anticipate the next thing I'll try is to write the text out to a bitmap or something and then use graphic routines instead.
I learned a few interesting things as I went, primarily because I have a long way to go in understanding proper layout in WPF. I originally used a Canvas in a StackPanel. The Canvas doesn't provide its content with a MaxWidth so I couldn't figure out a way to reliably wrap the text. I found several posts on forums as I Googled around with the same problem. I finally gave up and just used a Grid with my TextBlock in it. In this final version I played around with various DoubleAnimation features. Rather than hardcoding the "To" property I bound it to the height of the Grid. I also set AutoReverse so the text bounces up and down. That was mostly for my amusement since its not part of the specification. :-) For the application of course I'll want the From and To properties to be off the screen so I need to figure out how much text there is and size those numbers appropriately in code. It won't be the same amount every time in the final application.
Hope the XAML snippet helps someone playing with the same features someday.
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
I learned a few interesting things as I went, primarily because I have a long way to go in understanding proper layout in WPF. I originally used a Canvas in a StackPanel. The Canvas doesn't provide its content with a MaxWidth so I couldn't figure out a way to reliably wrap the text. I found several posts on forums as I Googled around with the same problem. I finally gave up and just used a Grid with my TextBlock in it. In this final version I played around with various DoubleAnimation features. Rather than hardcoding the "To" property I bound it to the height of the Grid. I also set AutoReverse so the text bounces up and down. That was mostly for my amusement since its not part of the specification. :-) For the application of course I'll want the From and To properties to be off the screen so I need to figure out how much text there is and size those numbers appropriately in code. It won't be the same amount every time in the final application.
Hope the XAML snippet helps someone playing with the same features someday.
<Grid x:Name="OurContainer">
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<TextBlock Text="Some text goes here and it must be long enough to wrap into the next line..."
FontSize="30" TextWrapping="Wrap" />
</ScrollViewer>
<Grid.RenderTransform>
<TranslateTransform x:Name="scroll" />
</Grid.RenderTransform>
<Grid.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever" >
<DoubleAnimation From="100"
To="{Binding ElementName=OurContainer, Path=Height}"
Storyboard.TargetName="scroll"
Storyboard.TargetProperty="Y"
Duration="0:0:5" SpeedRatio=".8" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Grid.Triggers>
</Grid>
</Window>
About The Author
Ron Grove draws on over ten years of training, network administration and development experience. He loves to work with new technology and see how that technology can be best utilized by his clients. You can find him through his company Evanoah, LLC and his LinkedIn profile is here.
Labels:
DoubleAnimation,
RenderTransform,
TextBlock,
WPF
Subscribe to:
Posts (Atom)