|
Manfred, have you ever used the notification service, I know we have never had to implement it and I am curious.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: I know we have never had to implement it and I am curious.
I have been exclusively doing backend database driven stuff often in high demand environments and the only 'need' I have ever seen for this is when some developer claims that it "could" happen. Analyzing actual business cases and actual usage has never demonstrated a need.
|
|
|
|
|
That has been my experience except I'm the developer so it has never happened, every now and then I have to slap a BA who suggests it to the users.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Indeed I always heard the rumors of SQL notification to subjugate LAN as RTS but caching one is like "fools gold".
|
|
|
|
|
Alok sharma ji wrote: 3. how does client A gets notification of SQL update by client B ;when both are viewing/working on same table. So the record can get an auto refresh or something like that. That's usually not done; the normal way is to fetch the data and show the snapshot as it was on the moment of fetching. Updating "live" data moves the concurrency-problem from the database (where it was solved) into your app, where you need to solve it yourself.
Simple example; you're editing a record, and the boss is editing the same one - you press "update" first. Now, how would you update the bosses record? Change the text in the textbox while he is editing/typing?
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
i think i will just put an edit lock for client 2 if client 1 is working on same table.
|
|
|
|
|
Alok sharma ji wrote: how does client A gets notification of SQL update by client B ;when both are viewing/working on same table.
That statement is a bit simple since it isn't a matter of working on the same table, since databases deal with that, but rather working on the same record (data) in the table. And that doesn't matter because it is very, very rare that there is an actual business case for that.
For example when a order center takes a customer order only one employee is taking the order. The customer is making the same order on two different phones lines.
|
|
|
|
|
Why are project files/classes organized by class type (Models folder, Repositories folder, Interfaces Folder), instead of business purpose (Account Objects, Employee Objects)?
I can understand storing reusable files in their own folder, but what about files that really only work when they are part of a unique and specific unit?
Organizing projects by class type seems like story left shoes in one room and right shoes in another room. You need a specific pair of shoes for them to work.
|
|
|
|
|
Mine aren't.
My are divided by function into separate projects:
Presentation (which may have multiple projects)
Business (Again, may well have multiple projects)
Utilities (ditto)
Data Access (normally just the one, but If I'm looking at multiple data sources, I'll probably break it that way as well)
How things are organised is up to you (or your company standards) - it's your project!
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
That's an interesting approach. What's the thinking behind that structure? Do you typically work with presenters alone, and then Data Access alone? Or do you usually work with a group of files from each project based on business process?
|
|
|
|
|
The thinking is that I can swap out my data access for a different datasource without affecting anything else in my application - or I can transport my business logic to a different machine, running Xamarin on an iPhone, or Android perhaps - and just provide the new presentation stuff. The less I have to change, the more reliable the whole should be.
What I work with depends on what I'm doing: I try to work on projects in isolation, with a tester module and only backtrack and make changes when it's clear they are needed.
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
OMVB wrote: but what about files that really only work when they are part of a unique and
specific unit?
That would be unusual.
OMVB wrote: instead of business purpose
Because business needs very seldom devolve to a single class. Even a single business need seldom devolves to that. A single business need is more likely to be fulfilled by multiple classes interacting together.
And in designing for a business there are often groupings of classes based on their common nature that represent layers. Because they are similar they are kept together.
|
|
|
|
|
Instead of a technical structure like this:
>Models
>>AccountModel
>>ContactModel
>>HouseModel
>Repositories
>>AccountRepo
>>ContactRepo
>>HouseRepo
Why not organize the project like this?
>BusinessObjects
>>Accounts
>>>AccountModel
>>>AccountRepository
>>Contacts
>>>ContactModel
>>>ContactRepository
|
|
|
|
|
If that was the only level of interaction, that would be fine, but how about talking to the database? What about system configuration or personalisation? What about an account for a contact? How about address maintenance?
|
|
|
|
|
Would it make sense for the account/contact relationship be first established at the DB via a foreign key?
ContactID
AccountID (foreign key)
ContactFirstName
ContactLastName
Then use the Account model and repo to grab a list of accounts from an account table or view, then use the Contact Model and Repo to grab the contacts related to a specific account?
There would certainly be some classes that would fall into a "common" category that would get reused, such as a db connection class, personalization and system configuration.
However, it seems like organizing some classes based on Business/DB Entity would make more sense then hunting around two or more folders to edit closely coupled class files, when certain class files only work as a unit.
I am still trying to figure this out.
|
|
|
|
|
You're cross cutting class responsibilities here. Don't think about what happens at the database level, think about what happens at the object level.
|
|
|
|
|
Hi,
A) In C# namespaces are purely logical sorting. So are the folders and files structure. This is all subjective. Make sure your API and structure is consistent so people know where to find stuff. That is it.
B) A project groups files, folders and resources and produces an assemblies/executable. This is where the tools introduce cons and pros regarding code structure. As an example what impact does visual studio and testing tools have on your code structure? (e.g. code generation when making a form introduce a certain file structure).
C) Your products need to be distributed, integrated, re-used, maintained/updated, etc. All this is about layering and splitting and thinking about dependencies. How well can you replace your logging functionality, add a new product platform or change a database dependency... and how do you keep the cost of making, testing and deploying the next feature as low as possible?
When you have a strategy for B) and C) you can go back to A) and make a logical decision. ½ a year later it might be that you would have preferred another logical decision, but at that time you stick with the old decision to avoid introducing new confusion. However, B) or C) might force you into re-ordering the code structure.
Kind Regards,
Keld Ølykke
|
|
|
|
|
OMVB wrote: Why not organize the project like this?
What part of my specific answer to that did you not understand?
|
|
|
|
|
I got the answer I needed, which isn't the one I was hoping for. The project will be for an application that creates a single assembly (client requirement). We have been looking at different structures to see how easily the typical C# developers could pick up the project and run with it, based on different file/folder structures.
There are a few instances where pairs or trios of file only work when all are in place. Similar to .ascx, .ascx.desinger, and .ascx.cs.
Its a good idea to test the waters before making these kinds of decision.
In general it appears C# devs are culturally inured to grouping files by technical purpose rather than business purpose, even if there is little reuse of object and the debugging worklfow would be much faster by having files grouped by business purpose.
Your answer was clear and its was VERY helpful! Thanks!
|
|
|
|
|
OMVB wrote: Why are project files/classes organized by class type (Models folder, Repositories folder, Interfaces Folder), instead of business purpose (Account Objects, Employee Objects)? Because programmers work with projects and types, and not with the abstractions called "Account Object". A code-solution is not an exact model of the business, and there's usually more types in a library than business objects.
OMVB wrote: Organizing projects by class type seems like story left shoes in one room and right shoes in another room. ..Yes, in the same way that a car has wheels in the front as well as in the back, but in the storage-room you'll find them on the same heap.
They're also not organized by "class", but by "target" or "goal"; there's no models-folder in my private projects, but models go together so that it's easy to find if I need a specific one. No, we don't have all resources in the same folder, but the resources that are considered a single package are.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
i everyone,i have a problem.i wan to scan my local network to get information about all the devices inside like OS name,Ip adresse netmask and mac adresse to realise a topologie of my network.thanks
|
|
|
|
|
|
|
Amusingly, that article would been called a code dump under the current criteria and probably relegated to a tip, how things change.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Hello,
I work at my school, I have a client-server application in C # with Visual Studio 2010 and I have my first client 1 that connects to server. but now I have a problem to connect a server to another client 2 in a VM (Virtual Machine: Virtual Box Windows 7).
Client 2:
* It should be the server connects to the client 2?
* The server sends a message to the client that son located in a virtual machine?
* After sent, the server received a confirmation message from client 2?
So it remains to create of client 2 code that receives a message from the server and client 2 sends a confirmation response to server and client 1?
so when I do the execution console server on my physical machine displays the following address: @ IP: 193.51.91.5:10000 & @ IP: 127.0.0.1:10000
and when I do the execution of the console server in the virtual machine (virtual box with windows 7) displays the following address: @ IP address: 192.168.56.1:10000 & @ IP: 127.0.0.1:10000
Please find attached client / server code.
Very thank you in advance and regards.
thank you
client :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using DPSBase;
using NetworkCommsDotNet;
namespace SocketProject.Client
{
class Program
{
#region [ Fields ]
private static ConnectionInfo connectionInfo = null;
private static Stopwatch _stopWatch = null;
#endregion
static void Main(string[] args)
{
string serverIP = string.Empty;
int serverPort = 0;
int loopCounter = 1;
TCPConnection serverConnection = null;
string result = string.Empty;
Console.WriteLine("SVP, saisissez l’adresse IP et le port du serveur (127.0.0.1:10000) : ");
Console.WriteLine();
string serverInfo = Console.ReadLine();
serverIP = serverInfo.Split(‘:’).First();
serverPort = int.Parse(serverInfo.Split(‘:’).Last());
while (true)
{
NetworkComms.RemoveGlobalIncomingPacketHandler();
connectionInfo = new ConnectionInfo(serverIP, serverPort);
serverConnection = TCPConnection.GetConnection(connectionInfo);
NetworkComms.AppendGlobalIncomingPacketHandler<string>("SendMessageToOthersClt", HandleIncomingCltMessage);
NetworkComms.AppendGlobalIncomingPacketHandler<string>("CustomObjectReply", HandleIncomingSrvMessage);
Console.Write(string.Format("Entrez votre {0}{1} message : \n ", loopCounter, (loopCounter == 0) ? "er" : "eme"));
string messageToSend = Console.ReadLine();
_stopWatch = new Stopwatch();
if (messageToSend.StartsWith("SendMsg"))
{
int firstSpace = messageToSend.IndexOf(‘ ‘);
serverConnection.SendObject("SendMessageToOthersClt", messageToSend.Substring(firstSpace));
}
else
serverConnection.SendObject("RequestCustomObject", messageToSend);
Console.WriteLine();
if (Console.ReadKey(true).Key == ConsoleKey.Q) break;
loopCounter++;
}
NetworkComms.Shutdown();
}
private static void HandleIncomingSrvMessage(PacketHeader header, Connection connection, string incomingMessage)
{
string messageToShow = string.Empty;
string execTime = string.Empty;
messageToShow = "——————————————————————————-\n";
string[] res = incomingMessage.Trim().Split(‘-’);
if (res.Length > 1)
execTime = ((_stopWatch.Elapsed.Milliseconds * 1000) + int.Parse(res[0])).ToString();
else
execTime = (_stopWatch.Elapsed.Milliseconds * 1000).ToString();
switch (res[1])
{
case "LaunchVM":
messageToShow += "Virtual Box Lancée après " + execTime + "(ns)\n";
break;
case "LaunchVagrant":
messageToShow += "Vagrant Lancée après " + execTime + "(ns)\n";
break;
case "SendMsg":
messageToShow += "Le message envoyée aprés " + execTime + "(ns)\n";
break;
default:
messageToShow += "Le message ‘" + res[1] + "‘ a été reçu par le serveur après " + execTime + "(ns)\n";
break;
}
messageToShow += "——————————————————————————-\n";
Console.Write(messageToShow);
}
private static void HandleIncomingCltMessage(PacketHeader header, Connection connection, string incomingMessage)
{
TimeSpan ts = _stopWatch.Elapsed;
Console.Write(string.Format("Message reçu de la part d’un autre client : {0} \n ", incomingMessage));
}
}
}
server:
using System;
using NetworkCommsDotNet;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DPSBase;
using System.Threading;
namespace SocketProject.Server
{
class Program
{
static void Main(string[] args)
{
NetworkComms.AppendGlobalIncomingPacketHandler<string>("RequestCustomObject", (packetHeader, connection, message) =>
{
Stopwatch stopWatchLaunchVagrant = new Stopwatch();
stopWatchLaunchVagrant.Start();
string msgConsole = string.Empty;
string elapsedTime = "";
string process = "";
string workingDirectory = "";
string arg = "";
msgConsole += "—————————————————————————–\n";
msgConsole += string.Format("Message reçu de la part Client {0}, le contenu est : {1} \n", "[" + connection.ConnectionInfo.NetworkIdentifier.Value + " " + connection.ConnectionInfo.LocalEndPoint.Address.ToString() + ":" + connection.ConnectionInfo.LocalEndPoint.Port.ToString() + "]", message);
if (message == "LaunchVM")
{
process = @"VirtualBox.exe";
workingDirectory = @"C:\Program Files\Oracle\VirtualBox\";
}
else if (message == "LaunchVagrant")
{
process = "cmd.exe";
workingDirectory = @"C:\Vagrant\";
arg = "vagrant up";
}
else if (message == "LaunchVagrantDistant")
{
process = "cmd.exe";
workingDirectory = @"\\dauphine-PC\Vagrant\";
arg = "vagrant up";
}
else if (message == "test")
{
process = "devenv.exe";
workingDirectory = @"C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\";
}
ProcessStartInfo psi = new ProcessStartInfo(process)
{
UseShellExecute = true,
RedirectStandardOutput = false,
RedirectStandardInput = false,
RedirectStandardError = false,
CreateNoWindow = true,
WorkingDirectory = workingDirectory
};
if (!(string.IsNullOrEmpty(arg)))
psi.Arguments = "/C " + arg;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);
stopWatchLaunchVagrant.Stop();
elapsedTime = (p.TotalProcessorTime.TotalMilliseconds * 1000 + stopWatchLaunchVagrant.ElapsedMilliseconds * 1000).ToString();
msgConsole += "Temps d’exécution est : " + elapsedTime + "\n";
msgConsole += "—————————————————————————–\n";
Console.Write(msgConsole);
connection.SendObject("CustomObjectReply", elapsedTime + "-" + message);
});
NetworkComms.AppendGlobalIncomingPacketHandler<string>("SendMessageToOthersClt", (packetHeader, connection, message) =>
{
string msgConsole = string.Empty;
msgConsole += "—————————————————————————–\n";
msgConsole += string.Format("Le Client {0} a envoyé ce message : \" {1} \" aux autres clients \n", "[" + connection.ConnectionInfo.NetworkIdentifier.Value + " " + connection.ConnectionInfo.LocalEndPoint.Address.ToString() + ":" + connection.ConnectionInfo.LocalEndPoint.Port.ToString() + "]", message);
var allRelayConnections = (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray();
foreach (var relayConnection in allRelayConnections)
{
try
{
relayConnection.SendObject("SendMessageToOthersClt", message);
}
catch (CommsException) { }
}
msgConsole += "—————————————————————————–\n";
Console.Write(msgConsole);
});
NetworkComms.AppendGlobalConnectionEstablishHandler((connection) => { Console.Write(string.Format(" Nouveau client connecté : [IP : {0}, PORT : {1}] \n", connection.ConnectionInfo.LocalEndPoint.Address.ToString(), connection.ConnectionInfo.LocalEndPoint.Port.ToString())); });
TCPConnection.StartListening(true);
foreach (System.Net.IPEndPoint localEndPoint in TCPConnection.ExistingLocalListenEndPoints())
Console.WriteLine("Serveur demarré – Infos : {0}:{1}", localEndPoint.Address, localEndPoint.Port);
Console.WriteLine("\n Cliquez sur une touche pour fermer le serveur.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
public static string elapsedTime { get; set; }
}
}
|
|
|
|
|