I'm trying to implement a transaction with entity framework 4. From what I've read, the code below is correct. The SaveChanges works fine but as soon as I hit the first ExecuteFunction call I get the following exception:
The underlying provider failed on
Open. --->
System.Transactions.TransactionManagerCommunicationException:
Network access for Distributed
Transaction Manager (MSDTC) has been
disabled. Please enable DTC for
network access in the security
configuration for MSDTC using the
Component Services Administrative
tool.
I've logged on to the database server and I don't see a service called Distributed Transaction Manager but I do see Distributed Transaction Coordinator and it is started. I'm not sure what I need to change to allow this to work. Anyone know? Thanks.
Here's the code.
using (var h = new WhaleEntities(ConnectionHelper.DBConnectString))
{
using (TransactionScope ts = new TransactionScope())
{
h.Sites.AddObject(s);
h.SaveChanges(SaveOptions.DetectChangesBeforeSave);
retval = s.SiteID;
h.ExecuteFunction("UpdateSiteInterfaceList", new ObjectParameter("pSiteID", retval), new ObjectParameter("pList", "10"));
h.ExecuteFunction("UpdateSiteInterfaceRequiredList", new ObjectParameter("pSiteID", retval),new ObjectParameter("pList", "Email"));
h.ExecuteFunction("UpdateSiteInterfaceAlwaysShownList", new ObjectParameter("pSiteID", retval),new ObjectParameter("pList", "10"));
h.ExecuteFunction("UpdateSiteInterfaceAlwaysRequiredList",new ObjectParameter("pSiteID", retval),new ObjectParameter("pList", "Email"));
ts.Complete();
//changes must be accepted manually once transaction succeeds.
h.AcceptAllChanges();
}
}
See here: How do I enable MSDTC on SQL Server?
Related
I have a windows desktop application on .NET Framework that a user can interact with. There is a "connect" button that sets up Apache Geode client connection to Geode Server.
When Geode Server is down (Locator - there is only 1) the desktop application hangs indefinitely and needs to be forcefully closed.
This is how we connenect to the server and hangs on last line indefinitely:
PoolFactory poolFactory = _cache.GetPoolManager()
.CreateFactory()
.SetSubscriptionEnabled(true)
.AddLocator(_host, _port);
return poolFactory.Create(_serviceName);
I would like to add a time-out period for this method to return or throw exceptions or anything.
Alternatively, I've wrapped it on a different kind of timer outside of this to just return, but when trying to run the above code again (to try to connect the application again) the pool is still trying to connect.
I have tried to destroy it like this:
//destroy the pool
var poolManager = _cache.GetPoolManager();
if (poolManager != null)
{
var pool = poolManager.Find(_serviceName);
if (pool != null && pool.Destroyed == false)
pool.Destroy();
}
But then the pool.Destroy(); hangs indefinateley
How can I have a mechanism to attempt to connect to the Geode server, return if not connected within 10 seconds, then leave and are able to try to connect again using the same cache?
Note above was trying to re-use the same cache, probably setting cache to null and trying all over again would work, but I am looking for a more correct way to do it.
Depending on what version of .NET native client you are using. There is a property in 10.x connect-timeout that should work. Additionally, you can wrap your connection code under try{...}catch{} block and handle an exception for Apache.Geode.Client.TimeoutException and/or ": No locators available".
Example:
var _cache = new CacheFactory()
.Set("log-level", "config")
.Set("log-file", "C:\temp\test.log")
.Set("connect-timeout", "26000ms")
.Create();
_cache.GetPoolManager()
.CreateFactory()
.SetSubscriptionEnabled(true)
.AddLocator(hostname-or-ip", port-number)
.Create("TestPool");
I am using the REST api for executing rules on Decision Server (Redhat Decision Manager 7.2) using a stateless kie session. I'm currently getting the number of triggered rules, but I also want to get the names of those rules. Is this possible?
KieServicesConfiguration conf = KieServicesFactory.newRestConfiguration(URL, USER, PASSWORD);
List<GenericCommand<?>> commands = new ArrayList<GenericCommand<?>>();
commands.add((GenericCommand<?>)
KieServices.Factory.get().getCommands().newInsert(applicant, "applicant"));
commands.add((GenericCommand<?>)
KieServices.Factory.get().getCommands().newInsert(loan, "loan"));
commands.add((GenericCommand<?>)KieServices.Factory.get().getCommands().newFireAllRules("numberOfFiredRules"));
KieCommands kieCommands = KieServices.Factory.get().getCommands();
BatchExecutionCommand batchCommand = kieCommands.newBatchExecution(commands, "default-stateless-ksession");
ServiceResponse<ExecutionResults> executeResponse = ruleServicesClient
.executeCommandsWithResults("loan-application_1.2.0", batchCommand);
System.out.println("Number of fired rules:" executeResponse.getResult().getValue("numberOfFiredRules"));
You have to use an AgendaEventListener to keep track of rules exectioned. By implemnting org.kie.api.event.rule.AgendaEventListener interface you can capture these detials.
To know which rules are triggered I added an action column with custom code (Action BRL fragment) that writes the rule name in one of the field of my fact. You can get it from rule.name.
Example:myFact.logMyRuleName(rule.name)
I'm using MVC5 with classic ADO.NET objects such as sqldatareader and sqldataadapter and sqlconnection and so on....
My controllers are creating a connection while initializing because I need to send the request object to the class holding the sqlconnection for something irrelevant to the question so my controller has an override void
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
db = new db(Request);
db.Connect();
}
Where db is my class and the method (connect) will create the sqlconnection object and open a connection...
and to close the connection I used the controller's dispose method as follows
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (db != null)
{
db.Close();
db = null;
}
}
and everything works fine then at one moment I got a weird server error (can't connect to db) please notice that my host is smarterasp.net
I can connect to database remotely using my home computer and I can connect to the web host as well so the problem is between my webhost and my database host, or between my application and my database host...
or it could be something related to the connection pooling even though the server error doesn't give me any details or stack trace(hens error is not inside my app thread)....
and I've fixed the problem by opening (remote iis) tab of smarterasp.net's control panel and clicked on (fix ACL) which I have no idea what it does but it fixed my problem.... temporarily :( unfortunately the problem reoccurred many times after that
so my question is in short format
is it good practice to open the connection while I'm initializing the controller and close it while the controller disposing???
and what do you think the error reason is??
finally I want to apologize if the question wasn't clear enough because English is not my first language (obviously)....
thanks a lot
so my question is in short format is it good practice to open the
connection while I'm initializing the controller and close it while
the controller disposing???
I do not think that is a good approach. You shouldn't open / close database connections and / or access the database from your controller. The controller should be as "thin" as possible. Additionally - the connection should be kept open for as short a period of time as possible and let ADO.NET connection pooling handle the details for you.
I also recommend wrapping your connection in a using block as it will implicitly call the close method:
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();
command.ExecuteNonQuery();
}
You did not say what the exact error is. At first glance, you aren't even checking to see if the connection is open before you try closing it. You should check the connection state before you try to explicitly close it and this should happen outside of the controller. Though I recommend that you wrap your SqlConnection in a using block (mentioned above).
EDIT
I read your comment. You are trying to manage the connection within the context of the controller's lifecycle and I suspect this is your issue.
If you were using Entity Framework (or possibly an another ORM), an IoC with "per-request lifestyle" - then the IoC container would properly dispose your context (connection) at the end of each request, and serve a new instance at each new one.
Perhaps this an option you can explore if you want to manage your database connection this way.
I have a web app that uses EF5 to map to a SQL database. This is the standard membership database with some additional tables I've added. Works like a champ in that project.
I have a second project, a windows service running TCP a server, which needs to insert items into the same database. So I reference the web app from this second project and can see my DbContext and entity types as needed.
At runtime, however, none of my DbSets gets populated with data. I have tried explicitly opening the connection to execute queries too, like this:
public MyContext()
: base("DefaultConnection")
{
try
{
Database.Connection.Open();
var command = new System.Data.SqlClient.SqlCommand("SELECT * FROM dbo.Trackers", (SqlConnection) Database.Connection);
var reader = command.ExecuteReader();
bool result = reader.Read();
}
catch (Exception exception)
{
//handle exception
}
this.Database.Connection.Close();
}
The result is false, but the connection is created and the reader is aware that I have four fields in my table. Is anyone aware of a reason this should work in my web app but not in a referencing app?
I had forgotten that the connection string from the web.config file is only honored when running as a web app. The TCP service .exe needs its own copy of the connection string in App.config. It just happened that the default (implicit) connection string on my TCP service connected to a valid, but empty, copy of my database.
In our SharePoint application we have used the UnitOfWork + Repository patterns together with Entity Framework. To avoid the usage of the passthrough authentication we have developed a piece of code that impersonate a single user before creating the ObjectContext instance in a similar way that is described in "Impersonating user with Entity Framework" on this site.
The only difference between our code and the referred question is that, to do the impersonation, we are using RunWithElevatedPrivileges to impersonate the Application Pool identity as in the following sample.
SPSecurity.RunWithElevatedPrivileges(delegate() {
using (SPSite site = new SPSite(url)) {
_context = new MyDataContext(ConfigSingleton.GetInstance().ConnectionString);
}
});
We have done this way because we expected that creating the ObjectContext after impersonation and, due to the fact that Repositories are receiving the impersonated ObjectContext would solve our requirement.
Unfortunately it's not so easy. In fact we experienced that, even if the ObjectContext is created before and under impersonation circumstances, the real connection is made just before executing the query, and so does not use impersonation, which break our requirement.
I have checked the ObjectContext class to see if there was any event through which we can inject the impersonation but unfortunately found nothing.
Any help?
We had a simillar problem when we used LinqToSharePoint. The DataContext is created from the HttpContext.Current and did not consider the RunWithElevatedPrivileges method. We did a nasty workaround that we backed up the original HttpContext, created a new dummy HttpContext in the RunWithElevatedPrivileges method and the problem went away. Obviously we set the context to the original afterwards.
Edit:
You can use the method below to create new dummy HttpContext.Call this method as first in your RunWithElevatedPrivileges. In the normal context just backup your currenct context with var backupContext = HttpContext.Current and after everything is done just set the context back.
private void SetNewContextWeb(SPWeb oWeb)
{
HttpRequest httpRequest = new HttpRequest(string.Empty, oWeb.Url, string.Empty);
HttpContext.Current = new HttpContext(httpRequest, new HttpResponse(new System.IO.StringWriter()));
SPControl.SetContextWeb(HttpContext.Current, oWeb);
}