|
I have the following situation:
I have an app that lives on an application server that will only be accessed via Terminal Services. Multiple users will be able to run this application. The actions of one user will affect the ability of other users to perform certain actions in their instance of the application.
Due to the nature of the application and file/registry access limitations of said server, I figure a service could be used as a marshal to implement that idea. The idea is that each user's app instance could communicate with the service to set/get access toggles (just two integers representing the object to be accessed, and a 1/0 toggle indicating whether or not access should be granted).
My questions are:
1) Can apps being run by multiple users via terminal services all access the service on the server? (I can't think of any reason they shouldn't be able to). If the answer to this is no, ignore the next few questions.
2) How do I find out if the service is even loaded from the application?
3) How would I exchange data with the service?
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
Seems to me there are a number of Windows-provided mechanisms you can use to synchronize access to things between intances of your application: events, timers, mutexes or semaphores.
As for how you could do interprocess communication, there're Named Pipes, sockets, or COM.
Ken....
|
|
|
|
|
I would choose either sockets or Pipes (pipes if you are not too good with sockets like me )
Actually once i worked on a service that watched a particular directory for command files (simple XML files) and performed the action specified in those XML files (works well if we only have one way communication), pretty lousy mechanism but worked beautifully through network shares
If you think you can than you can, if you think you can't you are right.
|
|
|
|
|
John Simmons / outlaw programmer wrote: 3) How would I exchange data with the service?
If both the service and the app are .NET you might look at using .NET Remoting.
led mike
|
|
|
|
|
Named pipes would probably be the easiest, or RPC/DCOM/Remoting, but sharing memory through mapped files and syncronizing with a mutex would have the best performance.
Using the GridView is like trying to explain to someone else how to move a third person's hands in order to tie your shoelaces for you.
-Chris Maunder
|
|
|
|
|
I am designing a *windows forms* application that displays data in a DataGridView.
The data is tabular, with about 12 columns, and with thousands of records.
The DataGridView data will be changed programmatically but it also can be changed by the user.
I want to be able to *locally persist* the DataGridView data from run to run; i.e., the PC may never connect to a remote database or may only occasionally connect.
I want to be able to programmatically delete old records to keep a ceiling on the number of records that share a thread ID.
My thoughts on where to locally persist the data are:
● INI file
● Windows Registry
● XML file
● Microsoft Access or other database
My thoughts on these:
● The INI file seems to be a nightmare to work with.
● The Windows Registry would be off-limits for some users and would probably quickly max out.
● The XML file seems to be favored in web forms rather than windows forms. Many XML controls and classes are in System.Web, which doesn't seem to be available in web forms.
● Microsoft Access probably would be cost-prohibitive, most of my users do not currently have it, its initial use of disk space seems to be high, and it can become bloated and need to be compacted. On the good side, having indexes and running SQL queries are both great. Maybe another database system would work if it has a small footprint, is easy to install, etc.
I'm hoping that someone can suggest a better option, give me some guidance, or give me a link to an implementation or example.
- Vkleo
|
|
|
|
|
Have a look at Smart Clients. This disconnected state is what they are designed for.
the last thing I want to see is some pasty-faced geek with skin so pale that it's almost translucent trying to bump parts with a partner - John Simmons / outlaw programmer
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
Thanks for your suggestion Pete. I looked into Smart Clients and I see that they are the type of application I am designing, but they do not really specify a good way to pull off the local persistence of data. They just state that it would be cached, or would use a local database, but then give no further specifics. That leads me back to the initial thoughts on using XML or some (currently unknown to me) free database that's easy to install and hook up. I did find the topic of WinFS intriguing, but I was left with the impression that that would only have widespread availability years in the future.
- Vkleo
|
|
|
|
|
Try the Smart Client Offline Application Block[^].
the last thing I want to see is some pasty-faced geek with skin so pale that it's almost translucent trying to bump parts with a partner - John Simmons / outlaw programmer
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
Thanks for the link Pete!
Pete O`Hanlon wrote: Try the Smart Client Offline Application Block[^].
That document led me to find "SQL Server Compact Edition", whose final release is expected this month. It's compact and allows SQL. I think it's free.
I believe the document is going to be an excellent guide for me going forward.
Thanks again!
- Vkleo
|
|
|
|
|
If you're using a DataSource as (no pun intended) the data source to the DataGridView then any can't you use the DataSource.WriteXml and DataSource.ReadXml routines?
The controls then don't care whether they're bound to an SQL database or an (in this case) an xml file.
vkleo wrote: Many XML controls and classes are in System.Web, which doesn't seem to be available in web forms.
Can you explain this a bit futher?
I have no idea what I just said. But my intentions were sincere.
|
|
|
|
|
Ed, I misspoke in my initial post, so let me explain what I meant to say. What I should have said was that the web forms toolbox contains controls like XML and XMLDataSource but the windows forms toolbox does not contain any obvious XML controls. I was thinking that web forms had more XML capabilities than windows forms, but it looks to me like windows forms will have sufficient XML capabilities for my needs.
My windows form now has a DataGridView , whose data source is a BindingSource (auto-created by Visual Studio), whose data source is a DataSet . During Form_Load I use DataSet.ReadXml and I'll use DataSet.WriteXml whenever I want to save.
I see that the DataSet creates its own "XML Schema", so I discarded my original hand-coded "XML Schema".
One of my technical advisors told me that he worked at a place that used XML files and used XSLT to query/filter the XML data. I could query/filter the XML data the same way, or maybe instead query/filter the data in the DataGridView . At first glance I would prefer not to access the data in the DataGridView but I'll need to think for a little while about the trade-offs between these two ways.
Thanks for the hint Ed!
- Vkleo
|
|
|
|
|
vkleo wrote: I could query/filter the XML data the same way, or maybe instead query/filter the data in the DataGridView.
No need to do either I think. If you want to create different views that's what the DataView component's for, if you insert this into the "chain" between the DataSource and the binding source then you can write regular SQL statements to filter / query the data.
The datasource will also allow to you query the data using SQL if you want as well.
(As far as I knew anyway the ASP binding way of things is waaaaayy behind the Windows.Forms way of doing things (even for Xml), just because they have Xml in their title doesn't mean their better. The only downside I suppose is that the WinForms versions do everything so aren't that lean and mean).
I have no idea what I just said. But my intentions were sincere.
|
|
|
|
|
Ed, I read up on the DataView and it certainly seems to be a better than the other 2 choices.
Ed.Poore wrote: [With] the DataView component... you can write regular SQL statements to filter / query the data.
Ed.Poore wrote: The datasource will also allow to you query the data using SQL if you want as well.
How would I run an SQL statement against the data? I didn't notice a method in either the DataView or the DataSet (i.e., the specific type of datasource that I populate using DataSet.ReadXml ) that allows me to use SQL. Can you show me a trivial line or two of code for each of these two classes?
- Vkleo
|
|
|
|
|
It's not exactly an SQL statement, but SQL syntax:
dataView.RowFilter = @"Country='UnitedKingdom' AND Surname='Poore'";
I have no idea what I just said. But my intentions were sincere.
|
|
|
|
|
Quite often, I have had to work (read fix here) with other people's database developments where they implement separate insert/update methods in the business layer.
A lot of the time, this doesn't actually make sense, and it is nicer just to provide a Save method where the save itself works out whether or not it needs to insert or update the record. As an example, consider the following Stored Procedure:
CREATE PROCEDURE [MyUser].[SaveUser]
@ID INT OUT,
@UserName NVARCHAR(30)
AS
SET NOCOUNT ON
IF @ID = 0
BEGIN
INSERT INTO UserDetails(ID, Name) VALUES (@ID, @UserName)
SET @ID = SCOPE_IDENTITY
END
ELSE
BEGIN
UPDATE UserDetails SET Name = @UserName WHERE ID = @ID
END
This means that the datalayer just needs to call the SaveUser procedure and the SP will work out whether it needs to do a save or an insert. Now, there are some arguments as to whether or not this is the responsibility of the datalayer, but look at how this simplifies procedure development. Instead of having Insert/Update/Delete, you end up having Save/Delete, thus simplifying your datalayer. The downside here is that you have to check the @ID field first, which is a (minor) performance hit that you may want to forego.
Alternatively, you could have the datalayer implement the same logic and determine whether or not this is an insert by checking the ID field beforehand.
public void Save()
{
if (_id == 0)
{
}
else
{
}
}
All I am asking, is that you remove the decision as to whether to insert or update from the business layer. Please...
the last thing I want to see is some pasty-faced geek with skin so pale that it's almost translucent trying to bump parts with a partner - John Simmons / outlaw programmer
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
Pete O`Hanlon wrote: Alternatively, you could have the datalayer implement the same logic and determine whether or not this is an insert by checking the ID field beforehand.
Or Alternatively you could let the data adapter do its job and make exactly the same decision for you.
Notice that the Data Adapter has only 2 main methods:
Fill - Executes your Select
Update - Executes your Insert,Update or Delete depending on the current state of the row being saved.
Sorry to say I 100% disagree with your oppinion that proper CRUD stored procedures are not a good thing.
|
|
|
|
|
J4amieC wrote: Or Alternatively you could let the data adapter do its job and make exactly the same decision for you.
Notice that the Data Adapter has only 2 main methods:
Fill - Executes your Select
Update - Executes your Insert,Update or Delete depending on the current state of the row being saved.
This only works if you are using a Data Adapter. In most cases, I have been dealing with more traditional business objects that are mapped into the database. For instance, having a Customer class and a Customers collection with the Customers collection being responsible for returning a number of populated Customer classes.
J4amieC wrote: Sorry to say I 100% disagree with your oppinion that proper CRUD stored procedures are not a good thing.
Where in my original post did I state that CRUD procedures are not a good thing? I present a couple of alternatives for saving data - one which uses a composite INSERT/UPDATE procedure, and the other which uses C# code to accomplish the same thing. What I did state was that it shouldn't be the responsibility of the business layer to work out whether to do an insert or an update. My last line was the important one:
All I am asking, is that you remove the decision as to whether to insert or update from the business layer. Please...
the last thing I want to see is some pasty-faced geek with skin so pale that it's almost translucent trying to bump parts with a partner - John Simmons / outlaw programmer
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
Pete O`Hanlon wrote: All I am asking, is that you remove the decision as to whether to insert or update from the business layer.
I agree and infact when I do use SPs I try and do this, makes the client code simpler and that's more likely to change so why make more work?
I have no idea what I just said. But my intentions were sincere.
|
|
|
|
|
Ed.Poore wrote: when I do use SPs I try and do this, makes the client code simpler and that's more likely to change so why make more work?
And that's the best approach that you can take.
the last thing I want to see is some pasty-faced geek with skin so pale that it's almost translucent trying to bump parts with a partner - John Simmons / outlaw programmer
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
(As is always the case) if the situation requires it, use it.
I have no idea what I just said. But my intentions were sincere.
|
|
|
|
|
I've worked on projects that supported this approach in the past.
I learned (the hard way) that I had to modify the business object to ensure that it had a valid ID.
So, I had to track state of the object. When loaded from the database, I set a hidden variable.
If the object was created from the database load, then an internal flag would hold that fact. If the object was not instantiated from the database, then the flag would never be set.
So maintaining state in the object allowed me to implement this technique.
However, it is much easier to have CRUD (Create, Read, Update and Delete) implemented on any single object representing a single record from the database. Which should map to the corresponding (Insert, Select, Update, Delete) procedures.
~ CodeDoctor ~
|
|
|
|
|
I am attempting to create a more efficient way to select data(like text). Before I used an index to the data that was stored in an array. I would have a separate collection or array that held the indexes of the data for another array. Each index in the "selection array" was selected. I think I have made a more efficient way to do that using two longs per selection, it does not matter how large the selection is, it will always be two longs. You can select multiple items. I'm using this in a application that can select data just like in notepad or a hex editor.
void SelectData(long start, long end)
{
_selected.Add(new Range(start, end));
if (_selected.Count > 1)
RemoveRangeRedundancies();
}
void RemoveRangeRedundancies()
{
foreach (Range rr in _selected)
{
foreach (Range r in _selected)
{
if (rr == r) continue;
if (rr.MinValue >= r.MinValue && rr.MaxValue <= r.MaxValue)
{
_selected.Remove(rr);
continue;
}
if (rr.MinValue <= r.MinValue && rr.MaxValue >= r.MaxValue)
{
_selected.Remove(r);
continue;
}
if (rr.MinValue < r.MinValue && (rr.MaxValue >= r.MinValue - 1) && rr.MaxValue <= r.MaxValue)
{
Range newRange = new Range(rr.MinValue, r.MaxValue);
_selected.Remove(rr);
_selected.Remove(r);
_selected.Add(newRange);
continue;
}
if (rr.MinValue >= r.MinValue && (rr.MinValue <= r.MaxValue + 1) && rr.MaxValue > r.MaxValue)
{
Range newRange = new Range(r.MinValue, rr.MaxValue);
_selected.Remove(rr);
_selected.Remove(r);
_selected.Add(newRange);
continue;
}
}
}
}
Do you think that is a good design?
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
Captain See Sharp wrote: it does not matter how large the selection is, it will always be two longs
Two ints would be just fine unless you anticipate working with buffers >1.99GB.
I haven't analyzed your code in depth, but it looks sufficient provided you don't have a large number of selection ranges (and in most cases you wouldn't). But if you think it would be wise to plan for that, then a double loop is not a good idea (O(N^2) performance overhead - i.e. the code in the inner loop is executed N*N times, where N is the number of ranges).
Performance-wise, it would be best to do the following (provided that you want the selection ranges to always stay non-overlapping). When adding a new range:- Do a binary search to find the insertion location for the range.
- Look at the range that is currently at the insertion location, and the one right before it. If the new change overlaps either of these, combine the new range with them.
- Insert the range at the insertion location (calculated via the binary search).
This will take significantly less time, and you have the added bonus of always having your selection range collection arranged in sorted order. That is what I did with text change ranges in a textbox I wrote for a client, where text changes are stored up and the text layout/flow is updated in a batched layout pass.
|
|
|
|
|
Thanks for you input.
I'm building a new version of my hex editor control just to let you know.
J. Dunlap wrote: Two ints would be just fine unless you anticipate working with buffers >1.99GB.
In the last version of my control I used ints. It was suffecient however in my new version I want it to be able to work with extremely large files. For large files I'm going to make it so it will not load the entire file so it wont use too much memory. If the program selects data that is not loaded into memory it will still need to know the index of the data so I will use longs.
A binary search would be a good idea and I may do that, How would I sort the ranges? Could I just add the MaxValue, MinValue, and Range together and sort by that sum?
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|