Alachisoft Ncache SqlCacheDependency adding dependency through stored procedure - c#

We are trying to implement SqlCacheDependency and while adding the dependency through Stored Procedure it remove the object immediately after adding it to cache.It gives CacheItemRemovedReason as 4.
We have used the Database Synchronization sample provided in mentioned below link.
http://www.alachisoft.com/resources/samples/
string storedProcName = "dbo.TestStoredProc1";
SqlCmdParams sqlParams = new SqlCmdParams();
sqlParams.Value = prod.ProductID;
//sqlParams.
Dictionary<string, SqlCmdParams> prms = new Dictionary<string, SqlCmdParams>();
prms.Add("ID", sqlParams);
_cache.Add(prod.ProductID.ToString(), item,DSWriteOption.None,null);
item.Dependency = new SqlCacheDependency(connString, "select * from dbo.state_lookup where state_id = " + prod.ProductID.ToString());
Database Synchronizationpublic void OnCacheDataModification(string key, CacheEventArg args)
{
switch (args.EventType)
{
case EventType.ItemAdded:
// Key has been added to the cache
Console.WriteLine(key + " Item Added");
break;
case EventType.ItemUpdated:
Console.WriteLine(key + " Item Updated");
break;
case EventType.ItemRemoved:
break;
}
I have added item change listener and it goes to ItemRemoved section immediatly after going into ItemAdded part.The item removed call back should get called only when data is changed in the database.
SQL Server Version : Microsoft SQL Server 2008 R2 (SP2)
Alachisoft Edition : Enterprise Trial Version
Alachisoft SDK version : 4.9.1.1

there are a few things that you need to look into while working with NCache SQLDependency and I have listed them below.
• NCache SQLDependency makes use of SQL Broker service to invalidate and remove items from cache based on notifications. Please make sure that you have enabled the broker service for your database so that NCache SQLDependency can work without any issues as mentioned in the steps here.
• Moreover, please note that SQLDependency has a few limitations on the statements that are supported when you create a query for SQLDependency. This limitation gets inherited by NCache SQLDependency feature as well since NCache depends upon SQL Broker. One of the main limitation is with the SELECT statement, which is that "The statement may not use the asterisk () or table_name. syntax to specify columns.". Your SQLDependency query should follow all the rules and requirements that have been mentioned by Microsoft.
• A complete list of requirements for creating a query for notification on SQL Server can be found at the following MSDN site: https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms181122(v=sql.105)
• Moreover, please note that whenever NCache SQLDependency fails to get registered, the corresponding item (for which the dependency was added) gets removed instantaneously, and an error message gets logged in the server logs. Please go through your server logs and you should be able to see an error entry stating that SQL Broker was unable to establish SQLDependency due to an invalid SQL query.
Once you have addressed all the above mentioned items, your SQLDependency should work flawlessly.

Related

How to prevent firing Dynamics CRM Plugin execution while updating an entity using web service?

I have implemented a plugin for my Dynamics CRM which is firing on Update message for incident entity.
Also I have a web service for external users which can update just two attributes of incident entity from outside.
The problem is while external users use the web service to update entity, the plugin will fire also.
I want to bind the plugin going to be fired just inside CRM when incident entity changed and prevent it firing by outside requests.
I checked below conditions in my plugin for preventing infinite loop and it works but not works for preventing firing by outside update requests.
if (context.Depth > 1 ||
context.Mode != 1 ||
context.MessageName != "Update" ||
context.IsolationMode != 1)
{
return;
}
To register plugin I've used the Plugin Registration Tool and I have set the step message to Update, and Run in User's Context as Calling User.
In my web service I've used Xrm.Sdk and Xrm.Sdk.Client to connect to CRM and update entity directly.
ColumnSet cs = new ColumnSet(new string[] {
"description", "statuscode"
});
Guid recordId = new Guid(caseID);
Entity currentRecord = crmService.Retrieve("incident", recordId, cs);
OptionSetValue osv = new OptionSetValue(1);
currentRecord["statuscode"] = osv;
currentRecord["new_answers"] = answer;
currentRecord["new_lastanswerdate"] = currentDate;
crmService.Update(currentRecord);
Anyone has any idea - How can I prevent plugin firing while an entity updated from outside of CRM?
The plugin executes in every server transaction & it gets triggered which is the expected behavior (that's the whole purpose).
You may use some other flag (additional attribute or any service account) which only get updated/used by outside integration, in that case you can check in execution context/target entity and ignore the further execution.
For external integration - you should create an Application user (non-interactive service account). Read more
I know it is a very old question, but there is a property of CrmServiceClient that allows you to bypass custom plugins from executing
You can find more details here CrmServiceClient - BypassPluginExecution

How do you connect from ODP.NET to Oracle (12G+) by proxy user with no password

There seems to be no answer online as to how you can use Oracle Data Provider for .NET (ODP.NET) to connect to Oracle (12G and later) in a very specific scenario:
User is identified externally on a database
User is granted access to another schema (application user) by proxy connect
User has been set up like this:
CREATE USER user_in_question
IDENTIFIED EXTERNALLY
-- etc.
And connect by proxy has been set up like this:
ALTER USER specified_app_user GRANT CONNECT THROUGH user_in_question
The logical approach when creating the ODP.NET OracleConnection string would be something like this (using the user friendly OracleConnectionStringBuilder):
var connBuilder = new OracleConnectionStringBuilder
{
UserID = "/", // External login using the user running the program
ProxyUserId = "specified_app_user",
DataSource = "database",
};
This does not work. Nor does providing blank "Password" or blank "Proxy Password". Nor does removing the UserId.
So how do you connect using ODP.NET in these circumstances?
The answer (which I spend an hour searching for without any luck) is actually really simple, yet not very user friendly:
var connBuilder = new OracleConnectionStringBuilder
{
UserID = "[specified_app_user]",
DataSource = "database",
};
//connBuilder.ToString() output:
//"USER ID=[specified_app_user];DATA SOURCE=database"
This works in .NET 4.5+ on Oracle 12G+, but probably also on earlier platforms of .NET/Oracle/ODP.NET. I did not test it in ASP.NET, but it should work there too.
This way the UserId actually functions just like the ProxyUserId, just enclosed within brackets, just as you would normally log in on the Oracle Database using, say, Toad or SQlPlus.
It might also be possible using this format (but in my case the connection string had to be compatible with the OraOLEDB format so that did not work):
//Without the use of the conn string builder class, just for the fun of it...
var connString = "User Id=specified_app_user;Data Source=database;Proxy User Id=/";
EDITED 2nd March 2017: The line above does not seem to work in certain cases. Added comment about it and here is the code that IS working:
USER ID=[specified_app_user];DATA SOURCE=database
This info does not seem to exist anywhere - else I overlooked it, and in that case PLEASE do correct me.

SqlDependency not updating cache

I'm on a project using .NET 4.5, MVC, EF 6
I had naively implemented a caching system using the HttpRuntime cache and needed to invalidate the data I cache on updates to that data; except I forgot to take into account that our production server is published to a load balanced set of two servers... :|
So on production, after the data was updated, the app would sometimes serve the right data, and sometimes the old data depending on which server the request was hitting. Bad news bears.
So I decided to define a dependency on the SQL table AcademicTerms which is where my data is coming from. But I did something wrong, and I'm not sure what.
SQL that I ran to set up the permissions after enabling the Service Broker
EXEC sp_addrole 'sql_dependency_role'
GRANT CREATE PROCEDURE to sql_dependency_role
GRANT CREATE QUEUE to sql_dependency_role
GRANT CREATE SERVICE to sql_dependency_role
GRANT REFERENCES on
CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]
to sql_dependency_role
GRANT VIEW DEFINITION TO sql_dependency_role
GRANT SELECT to sql_dependency_role
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO sql_dependency_role
GRANT RECEIVE ON QueryNotificationErrorsQueue TO sql_dependency_role
EXEC sp_addrolemember 'sql_dependency_role', 'MY_ASPNET_APP_USERNAME'
My implementation of inserting new data after fetching and thus setting up the SqlDependency (hopefully less naive!):
private void insertIntoCache(
AcademicTermLockingInfo newItem,
string itemKey,
Guid termID) {
var dbContextConnection = db.Database.Connection;
var connectionString = dbContextConnection.ConnectionString;
// important step otherwise it won't work
SqlDependency.Start(connectionString);
CacheItemPolicy policy = new CacheItemPolicy {
AbsoluteExpiration = DateTime.UtcNow.AddMonths(6)
};
CacheItem item = new CacheItem(itemKey, newItem);
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
// command which will be used to notify updates - probably want to parametrize this
using (SqlCommand command =
new SqlCommand(
String.Format("SELECT Name, LockDate FROM dbo.AcademicTerms WHERE ID = '{0}'",
termID),
connection)) {
SqlDependency dependency = new SqlDependency(command);
SqlChangeMonitor monitor = new SqlChangeMonitor(dependency);
policy.ChangeMonitors.Add(monitor);
MemoryCache.Default.Set(item, policy);
// execute once otherwise dependency not registered
command.ExecuteNonQuery();
}
}
}
Any help would be very much appreciated!
Things I've done:
Created two new users in SQL Server, net and sanba
Added every NT* login and the sa login to the net user, added net to the sql_dependency_role
Ran grant alter on schema::sql_dependency_role to net and grant alter on schema::dbo to net
Check that my local SQL Server's Broker Enabled option is True under Service Broker
Tried the web cache and the Memory Cache interchangeably (probably wouldn't change anything)
Tried making the sql command string have a fully qualified name DevUMS.dbo.AcademicTerms and dbo.AcademicTerms
I queried the sys.dm_qn_subscriptions and saw I had one subscription, good!
I queried DevUMS.sys.transmission_queue and found an excpetion!
An exception occurred while enqueueing a message in the target
queue. Error: 15517, State: 1. Cannot execute as the database
principal because the principal "dbo" does not exist, this type of
principal cannot be impersonated, or you do not have permission.
I found this SO post with the same error
The secret sauce I was missing was alter authorization on database::DevUMS to [sa]; which I found on the linked SO post's answer.
There are a number of other steps, like adding a Role to use the appropriate login, but honestly, I'm really unsure as to whether or not those are actually necessary.
I'm going to publish a little later on today, and then I'll try to do the minimal amount of steps and document that here. I found the documentation in the wild to be very scattered and poor, so I hope to have this answer be a definitive place to refer to in the future

Azure Mobile Services PullAsync() Not Filling Sync Table

So I have a remote table called Profile that has multiple entries made already. Now I'm trying to integrate offline capabilities into my application. As of right now I'm having issues with PushAsync and PullAsync methods in my code.
I would like to be able to copy all the data from my remote table into my local table just by calling PullAsync, and although it doesn't throw any exceptions it also doesn't populate my table. Here's an example of what I mean.
var db = new SQLiteConnection("syncstoreTEMP.db");
var store = new MobileServiceSQLiteStore("syncstoreTEMP.db");
store.DefineTable<Profile>();
MobileService.SyncContext.InitializeAsync(store).Wait();
var remoteValues = MobileService.GetTable<Profile>()
.ToListAsync()
.Result;
MobileService.GetSyncTable<Profile>()
.PullAsync(null, MobileService.GetSyncTable<Profile>().CreateQuery())
.Wait();
var localValues = MobileService.GetSyncTable<Profile>()
.ToListAsync()
.Result;
When I run this code remoteValues has a total length of 5, but localValues still shows 0 entries even after issuing a Pull from remote. How can I get the sync table to match my remote table?
It's strange that you're not getting any exceptions, but you seem to be creating two connections to your local store. You should not have the line for new SQLiteConnection, only the line that creates the MobileServiceSQLiteStore.
Here's a tutorial that walks through how to set things up: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-xamarin-ios-get-started-offline-data/
I also recommend that you add a DelegatingHandler to your MobileServiceClient in order to log all of the requests and responses. Then you can see exactly what's going wrong. Here's a sample that shows this, and also includes a logging extension to the SQLite store so you can see exactly what is happening locally: https://github.com/paulbatum/FieldEngineerLite/blob/master/FieldEngineerLite.Client/FieldEngineerLite/Helpers/LoggingHelpers.cs

Using SMO.Agent to retrieve SQL job execution status - security issue

I've got a C# program that fires off SQL Server Agent jobs using the SQL Server Management Objects (SMO) interfaces. It looks something like:
Server ssis_server = new Server(
new ServerConnection(SERVER_NAME, SERVER_USERNAME, SERVER_PASSWORD)
);
var agent = ssis_server.JobServer;
var ssis_job = agent.Jobs[job_name];
var current_status = ssis_job.CurrentRunStatus;
if (current_status == JobExecutionStatus.Idle)
{
ssis_job.Start();
OnSuccess("Job started: " + job_name);
}
else
{
OnError("Job is already running or is not ready.");
}
I'm using SQL Server Authentication at this point to simplfy things whilst I work this out.
Now, my problem is that unless the SERVER_USERNAME is part of the 'sysadmin' dbo role, ssis_job.CurrentRunStatus is always 'Idle' - even when I know the job is running. It doesn't error out, just always reports idle.
If the user is an administrator, then the status is returned as expected.
Role membership you say?
Well, I added the SERVER_USERNAME SQL Server login to the msdb Role SQLAgentOperatorRole, that didn't seem to help.
The job's owner is a system administrator account - if that's the issue I'm not sure how to work around it.
Any ideas?
You need to refresh the job by calling the Refresh() method on ssis_job before checking the status, then you will get the correct information.

Categories