We have windows application and used SqlDependency for notification. Day by day application and database goes huge and it works slow.
Any best way to get notified like SqlDependency? We need similar change update in application like SqlDependency.
Any other solution? or way in Sql Server 2014.
Please suggest.
Thanks.
You can use an open source realization of the SqlDependency class - SqlDependencyEx. It uses a database trigger and native Service Broker notification to receive the events about the table changes. This is an usage example:
int changesReceived = 0;
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME))
{
sqlDependency.TableChanged += (o, e) => changesReceived++;
sqlDependency.Start();
// Make table changes.
MakeTableInsertDeleteChanges(changesCount);
// Wait a little bit to receive all changes.
Thread.Sleep(1000);
}
Assert.AreEqual(changesCount, changesReceived);
Hope this helps.
Related
i'm feeling confused, which are best practices between laravel observer or MySQL Trigger.
In Laravel, My Code looks like
public function updated(My_Activity $my_activity)
{
$activity = new Activity_Log();
$activity->activity_id = $my_activity->id;
$activity->status = $my_activity->status;
$activity->description = $my_activity->description;
$activity->save();
}
In MySQL,
BEGIN
INSERT INTO Activity_Log
SET id = OLD.id, status = OLD.status, description = OLD.description
END
What is the best practice ? Is there a good impact for one of them in the future?
I prefer Laravel Observer option because it allows you to keep your business logic in your application (source control). Additionally you keep your business logic at the same abstraction level by using Eloquent.
For the same reason Laravel introduced a Task scheduler. It allows you to keep your cron entries under source control.
https://laravel.com/docs/5.5/scheduling
In the past, you may have generated a Cron entry for each task you
needed to schedule on your server. However, this can quickly become a
pain, because your task schedule is no longer in source control and
you must SSH into your server to add additional Cron entries.
I recently ran into an instance where I wanted to hit the database from a Task I have running periodically within a web application. I refactored the code to use the ThreadStaticSessionContext so that I could get a session without an HttpContext. This works fine for reads, but when I try to flush an update from the Task, I get the "Index was out of range. Must be non-negative and less than the size of the collection." error. Normally what I see for this error has to do with using a column name twice in the mapping, but that doesn't seem to be the issue here, as I'm able to update that table if the session is associated with a request (and I looked and I'm not seeing any duplicates). It's only when the Task tries to flush that I get the exception.
Does anyone know why it would work fine from a request, but not from a call from a Task?
Could it be because the Task is asynchronous?
Call Stack:
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.System.Collections.IList.get_Item(Int32 index)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
Session Generation:
internal static ISession CurrentSession {
get {
if(HasSession) return Initializer.SessionFactory.GetCurrentSession();
ISession session = Initializer.SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
return session;
}
}
private static bool HasSession {
get { return CurrentSessionContext.HasBind(Initializer.SessionFactory); }
}
Task that I want to access the database from:
_maid = Task.Factory.StartNew(async () => {
while(true) {
if(CleaningSession != null) CleaningSession(Instance, new CleaningSessionEventArgs { Session = UnitOfWorkProvider.CurrentSession });
UnitOfWorkProvider.TransactionManager.Commit();
await Task.Delay(AppSettings.TempPollingInterval, _paycheck.Token);
}
//I know this function never returns, I'm using the cancellation token for that
// ReSharper disable once FunctionNeverReturns
}, _paycheck.Token);
_maid.GetAwaiter().OnCompleted(() => _maid.Dispose());
Edit: Quick clarification about some of the types above. CleaningSession is an event that is fired to run the various things that need to be done, and _paycheck is the CancellationTokenSource for the Task.
Edit 2: Oh yeah, and this is using NHibernate version 4.0.0.4000
Edit 3: I have since attempted this using a Timer, with the same results.
Edit 4: From what I can see of the source, it's doing a foreach loop on an IList. Questions pertaining to an IndexOutOfRangeException in a foreach loop tend to suggest a concurrency issue. I still don't see how that would be an issue, unless I misunderstand the purpose of ThreadStaticSessionContext.
Edit 5: I thought it might be because of requests bouncing around between threads, so I tried creating a new SessionContext that combines the logic of the WebSessionContext and ThreadStaticSessionContext. Still getting the issue, though...
Edit 6: It seems this has something to do with a listener I have set up to update some audit fields on entities just before they're saved. If I don't run it, the commit occurs properly. Would it be better to do this through an event than OnPreInsert, or use an interceptor instead?
After muddling through, I found out exactly where the problem was. Basically, there was a query that was run to load the current user record called from inside of the PreUpdate event in my listener.
I came across two solutions to this. I could cache the user in memory, avoiding the query, but having possibly stale data (not that anything other than the id matters here). Alternatively, I could open a temporary stateless session and use that to look up the user in question.
I am develping an app which load some url, parse them, keep them into sqlite db and the UI will read the saved data and show them in controls. This progress should be done in almost an infinit loop. For having fast response i plan to read the data from db in main thread and have an other thread (background worker) to load the data and insert it into db. Is it logical and possible to run read and write process in dispatchertimer, one timer in main thread and the other inside the background worker? and how? Or does anyone have better idea?
main thread:
DispatcherTimer _Timer1 = new DispatcherTimer();
_Timer1.Interval = _Interval;
_Timer1.Tick += _Timer1_Tick;
void _Timer1_Tick(object sender, EventArgs e)
{
// read data from db and show in controls
}
secondary thread:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
DispatcherTimer _Timer2 = new DispatcherTimer();
_Timer2.Interval = _Interval;
_Timer2.Tick += _Timer2_Tick;
}
void _Timer2_Tick(object sender, EventArgs e)
{
// write data into db
}
}
What you're planning to do wont work.
Both your _Timer1_Tick and _Timer2_Tick will run in the UI thread. If you perform some long-running operations there, it'll hang the UI.
I don't get it, why do you need timers at all? Using timers for anything else but measuring time intervals is rarely a good strategy. You could e.g. run your update process in the infinite loop in background, as soon as it put new data in the DB you call Dispatcher.BeginInvoke (passing any data you want) to notify your UI thread it should update itself with the newly available data.
And by the way, for the tasks like "send HTTP request, wait response, parse, store, repeat", the new async/await feature is a natural choice. For WP7 the functionality is available as "Async CTP" redistributable package for Visual Studio 2010, for WP8 it's already integrated into the framework. There're some compatibility issues between the 2, though.
load some url, parse them, keep them into sqlite db and the UI will read the saved data and show them in controls
Please don't do that. Don't create your own thread management system, just don't. I'm not saying it won't work, but it'll most likely backfire in the most horrendous and inexplicable ways. Like for example using a DisptacherTImer completely exploding in your face since it runs on the UI thread. If you really want to use threading considering ThreadPool.QueueUserWorkItem() or Task.Run() to start fire-and-forget actions.
Your workflow is also just strange, I don't get why you need to write data you already have to a DB, then read it back and only then use it. Won't it make more sense to use the deserialized data to sequentially write it to the DB and present it to the UI? Instead of doing the needless loop of involving Disk I/O considering you already have the data?
Have you considered using Messaging in your app? It's a pretty well known MVVM pattern implemented both in MVVM Light as the Messenger class and in PRISM as the EventAggregator. It seems to me that your system has a Message for "new data available from service" and that message has two subscribers: writing to a DB and updating the UI.
We are trying to develop a small application that can monitor the programs/processes that are executing in a windows machine.
If the program/process is not supposed to run, it should be blocked. It works similar to an antivirus.
This is the basic idea.
I want to know the ways to hook into the OS to get notified about every single program/process trying to run in the machine.
The easiest way is to use WMI. Specifically monitor the Win32_ProcessStartTrace. This is better than Win32_Process, because it is setup to use events whereas Win32_Process requires polling which is more CPU intensive. Below is how to do it in C#. First make sure that System.Management is setup as a reference for your project.
public System.Management.ManagementEventWatcher mgmtWtch;
public Form1()
{
InitializeComponent();
mgmtWtch = new System.Management.ManagementEventWatcher("Select * From Win32_ProcessStartTrace");
mgmtWtch.EventArrived += new System.Management.EventArrivedEventHandler(mgmtWtch_EventArrived);
mgmtWtch.Start();
}
void mgmtWtch_EventArrived(object sender, System.Management.EventArrivedEventArgs e)
{
MessageBox.Show((string)e.NewEvent["ProcessName"]);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
mgmtWtch.Stop();
}
The code will generate a messagebox everytime you launch a new process. From there you can check a whitelist/blacklist and act appropriately.
I havn't tried geting real-time notification. How ever, Here is how to get running processes in C#
using System.Diagnostics;
//Somewhere in your method
Process[] runningList = Process.GetProcesses();
foreach(Process p in runningList){
Console.WriteLine("Process: {0} ID: {1}", p.ProcessName, p.Id);
}
You can also use the following props of a process
StartTime - Shows the time the process started
TotalProcessorTime - Shows the amount of CPU time the process has taken
Threads - gives access to the collection of threads in the process
I would check up the Win32-api SetWindowsHookEx with the constant WH_GETMESSAGE to add a callback to your program when a new window is being created.
http://pinvoke.net/default.aspx/user32.SetWindowsHookEx
Google that API and WH_GETMESSAGE to find out more.
Also check out the following articles/code librarys:
http://www.vbaccelerator.com/home/Vb/Code/Libraries/Hooks/vbAccelerator_Hook_Library/article.asp
http://www.codeproject.com/KB/DLL/hooks.aspx?fid=2061&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=76&select=726975
Our team is creating a new recruitment workflow system to replace an old one. I have been tasked with migrating the old data into the new schema. I have decided to do this by creating a small Windows Forms project as the schema are radically different and straight TSQL scripts are not an adequate solution.
The main sealed class 'ImportController' that does the work declares the following delegate event:
public delegate void ImportProgressEventHandler(object sender, ImportProgressEventArgs e);
public static event ImportProgressEventHandler importProgressEvent;
The main window starts a static method in that class using a new thread:
Thread dataProcessingThread = new Thread(new ParameterizedThreadStart(ImportController.ImportData));
dataProcessingThread.Name = "Data Importer: Data Processing Thread";
dataProcessingThread.Start(settings);
the ImportProgressEvent args carries a string message, a max int value for the progress bar and an current progress int value. The Windows form subcribes to the event:
ImportController.importProgressEvent += new ImportController.ImportProgressEventHandler(ImportController_importProgressEvent);
And responds to the event in this manner using it's own delegate:
private delegate void TaskCompletedUIDelegate(string completedTask, int currentProgress, int progressMax);
private void ImportController_importProgressEvent(object sender, ImportProgressEventArgs e)
{
this.Invoke(new TaskCompletedUIDelegate(this.DisplayCompletedTask), e.CompletedTask, e.CurrentProgress, e.ProgressMax);
}
Finally the progress bar and listbox are updated:
private void DisplayCompletedTask(string completedTask, int currentProgress, int progressMax)
{
string[] items = completedTask.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
foreach (string item in items)
{
this.lstTasks.Items.Add(item);
}
if (currentProgress >= 0 && progressMax > 0 && currentProgress <= progressMax)
{
this.ImportProgressBar.Maximum = progressMax;
this.ImportProgressBar.Value = currentProgress;
}
}
The thing is the ListBox seems to update very quickly, but the progress bar never moves until the batch is almost complete anyway ??? what gives ?
Maybe you can try the BackgroundWorker component. It makes threading easier. Examples here:
BackgroundWorker Threads and Supporting Cancel
Using the BackgroundWorker Component in .NET 2 applications
BackgroundWorker Sample
Maybe outside of the scope but, to sometimes its useful to do an Application.DoEvents(); to make the gui parts react to user input, such as pressing the cancel-button on a status bar dialog.
Do you by any chance run Windows Vista? I've noticed the exactly same thing in some work related applications. Somehow, there seem to be a delay when the progress bar "animates".
#John
Thanks for the links.
#Will
There's no gain from threadpooling as I know it will only ever spawn one thread. The use of a thread is purely to have a responsive UI while SQL Server is being pounded with reads and writes. It's certainly not a short lived thread.
Regarding sledge-hammers you're right. But, as it turns out my problem was between screen and chair after all. I seem to have an unusal batch of data that has many many many more foreign key records than the other batches and just happens to get selected early in the process meaning the currentProgress doesn't get ++'d for a good 10 seconds.
#All
Thanks for all your input, it got me thinking, which got me looking elsewhere in the code, which led to my ahaa moment of humility where I prove yet again the error is usually human :)
Are you sure that the UI thread is running freely during all this process? i.e. it's not sitting blocked-up on a Join or some other wait? That's what it looks like to me.
The suggestion of using BackgroundWorker is a good one - definitely superior to trying to sledge-hammer your way out of the problem with a load of Refresh/Update calls.
And BackgroundWorker will use a pool thread, which is a friendlier way to behave than creating your own short-lived thread.
There's no gain from threadpooling as
I know it will only ever spawn one
thread. The use of a thread is purely
to have a responsive UI while SQL
Server is being pounded with reads and
writes. It's certainly not a short
lived thread.
OK, I appreciate that, and glad you found your bug, but have you looked at BackgroundWorker? It does pretty much exactly what you're doing, but in a standardised fashion (i.e. without your own delegates) and without the need to create a new thread - both of which are (perhaps small, but maybe still useful) advantages.