The PCTradeOffice sample demonstrates how a complex application might use Data Abstract for .NET to provide access to the PCTrade database (accessed through the PCTrade schema) and allow the user to browse and edit the content much like a "real" client application would. Principally the sample uses DA LINQ to interact with the schema data.
The sample is typically located in
C:\Program Files (x86)\RemObjects Software\Data Abstract for .NET\Samples\C#\PCTradeOffice, though you may have installed the Data Abstract for .NET SDK and it's samples in another location.
To build it, you will of course need Visual Studio, and like all the samples provided with Data Abstract for .NET you will need to be running Relativity Server with the
DASamples Domain and the
PCTrade Schema available.
Running the Sample
This sample allows you to view & alter the content of a number of different tables, from the point of view of users who have different levels of access. When the sample first starts it presents the main UI and a login dialog with three users that can be selected.
Each of three users have different access levels which provide different abilities:
- Mollie Bennet the Managing Director of the fictional company. She has access to all of the data and can view all of of the available views. In the "Orders" view she has access to all of the data unlike the other two users. She also can view the special "Sales Report" data.
- Gale Dalton who is the Income Manager, she is only able to view the "Orders", "Price List" and "Providers". Her "Orders" table is filtered to only show the orders that she has originated.
- Sandy Manning who is the Sales Manager, she is can only view the "Orders" and "Clients" tables.
Simply click on the user you want and then press the "Login" button. Once logged in you will have a number of the tab like views available. Each one presents data retrieved from multiple tables in the remote schema. Note not all of those views are available to every user in the system.
- The Users tab provides a means to switch to different users, as well as see the access rights for that user. When you press the "Change user" button the login dialog is again presented.
- The Orders view displays data retrieved from the "Orders", "OrderDetails", "PriceList" and "RestReport" tables. Many of the fields on display are added using Lookup and Calculated fields. The data returned from the server is filtered based on the user accessing the server using Business Rules Scripting and Dynamic Where.
- The PriceList view takes data from the "Products" and "PriceList" tables are presents the data in a tree like structure.
- The Clients view displays a table of all of the clients in the "Clients" table, and allows the user to add, edit or delete them.
- The Providers view similarly displays a table of all of the stock providers in the "Providers" table and allows the user to add, edit or delete them.
- The Reports view is only available to the managing director user, it uses a special "SalesReport" table in the PCTrade schema that uses custom SQL to pull together data from multiple schema tables and return that. The "SalesReport" table can be passed two parameters (a start and end date) that then filters the data based on those dates.
Examining the Code
This section gives an overview of the classes that makes up this sample as well as specific details related to using the classes provided by Data Abstract for .NET.
The sample is built around many different classes though the principle class is
DataModule as it handles the interaction with the instance of Relativity Server including retrieving data, logging into and out of the server and retrieving the profile image for the logged in user.
The PCTrade_TableDefinitions class is machine generated from the PCTrade.relativityClient file. It provides concrete classes for the tables in the schema and their rows. Those classes are used throughout the sample for displaying and manipulating field data.
MainWindow defines the basic user interface with the tabs, and works in concert with MainWindowViewModel which creates an instance of DataModule, creates view models for each of the tab views available in the sample, and handles other user interface related operations like determining which tab will be visible first after a user logs in.
Each tab ("Orders", "PriceList", "Clients", "Providers" and "Reports") has a "Repository" class which uses the DataModule and the
LinqRemoteDataAdapter to provide methods for inserting, updating and deleting a row, as well as selecting a specific row or all rows. The tab also has "View" and "ViewModel" classes which handle defining the tab's visual interface and the code to handle the user interaction.
Rather than using the
RemoteDataAdapter that other samples use, this sample uses the
LinqRemoteDataAdapter class. It, like the
RemoteDataAdapter, is a Data Adapter that handles the communication between the client program and the server. Configuration the connection and handling login is identical between the classes, but how they interact with the schema and tables is different. Note that the
LinqRemoteDataAdapter adapter does not support Dynamic Where or Dynamic Select per se, but you can use DA LINQ to achieve the same results.
LinqRemoteDataAdapter also handles tracking the changes to the table data (for instance adding a new row, or deleting an existing one) until the
ApplyChanges method is called. At this point all local changes will be applied to the server.
Retrieving Data with DA LINQ
A typical DA LINQ query is shown below. The first part retrieves the table using the
LinqRemoteDataAdapter, which will be the data source for the remainder of the DA LINQ query. You can then use standard
LINQ queries to work with the data. In this sample, the DA LINQ query selects all the rows and fields from the
Products table. After the query is complete, the sample converts the results to a
// line taken from DataModule.cs - public List<Products> ProductList property fProductsList = (from t in DataAdapter.GetTable<Products>() select t).ToList<Products>();
Applying Changes to the server
In this sample the
ApplyChanges method is called immediately after a row has been inserted into a table, updated or deleted.
// line taken from ClientsRepository.cs - public override void Insert(Clients entity) DataModule.SharedInstance.DataAdapter.ApplyChanges();
Adding a row
Adding a new row when using
LinqRemoteDataAdapter is different than when normally using Data Abstract. Instead of adding the row to a
DataTable and using a
DeltaChange object to store the data and apply those changes to the server, you instead use concrete data classes which map to a row in the table and then pass those to the Data Adapter.
After you've created the data object (here an instance of the
Clients), it needs to be passed to the
InsertRow method of
LinqRemoteDataAdapter data adapter will track all of the changes to the data and apply them to the server when the
ApplyChanges method is called.
// line taken from ClientsRepository.cs - public override void Insert(Clients entity) DataModule.SharedInstance.DataAdapter.InsertRow<Clients>(entity);
Updating a row
// line taken from ClientsRepository.cs - public override void Update(Clients entity) DataModule.SharedInstance.DataAdapter.UpdateRow<Clients>(entity);
Deleting a row
// line taken from ClientsRepository.cs - public override void Delete(Clients entity) DataModule.SharedInstance.DataAdapter.DeleteRow<Clients>(entity);