I have DTC configured as outlined on MS website to support for remote transaction. I have the following code always giving me error.
using (TransactionScope ts = new TransactionScope())
{
Category c = new Category();
c.Name = "Cat1";
c.Save();
Product p = Product.SingleOrDefault(x=>x.ProductID==1);
p.Title = "new title";
p.Save();
ts.Close();
}
However if I move the second block of code out of the suing block it works just fine. What I want to do is bind those two block of code into one trascation. What could be the readon? Thanks,
You don't specify what error the code is giving you but the only thing wrong I can see is that you're not calling Complete on your TransactionScope. Try the following:
using (TransactionScope ts = new TransactionScope())
{
Category c = new Category();
c.Name = "Cat1";
c.Save();
Product p = Product.SingleOrDefault(x=>x.ProductID==1);
p.Title = "new title";
p.Save();
ts.Complete();
}
You shouldn't actually need DTC enabled, you can wrap this code in a transaction using SubSonic's SharedDbConnectionScope. Try the following:
using (TransactionScope ts = new TransactionScope())
using (SharedDbConnectionScope sharedConnectionScope = new SharedDbConnectionScope())
{
Category c = new Category();
c.Name = "Cat1";
c.Save();
Product p = Product.SingleOrDefault(x=>x.ProductID==1);
p.Title = "new title";
p.Save();
ts.Complete();
}
Related
I had wrote some code for creating po via code, but it faild with error message: "CS Error: Cannot generate the next number for the sequence."
How can I fix this? Anything I missed? Thx for helping!
protected void createPO() {
POOrder order = new POOrder();
POOrderEntry graph = PXGraph.CreateInstance < POOrderEntry > ();
order.OrderType = "Normal";
order.OrderDesc = "some text";
order.EmployeeID = 215;
order.Hold = false;
var branch = (Branch)PXSelect<Branch, Where<Branch.branchCD, Equal<Required<Branch.branchCD>>>>.Select(Base, "WEST");
graph.FieldDefaulting.AddHandler<POOrder.branchID>((s, e) =>
{
e.NewValue = branch.BranchID;
e.Cancel = true;
});
order.VendorID = 79;
order = graph.CurrentDocument.Insert(order);
graph.CurrentDocument.Update(order);
graph.Actions.PressSave();
throw new PXRedirectRequiredException(graph, null);
}
Try to simply it first to see if something like this works...
protected void createPO()
{
var graph = PXGraph.CreateInstance<POOrderEntry>();
var order = graph.Document.Insert(new POOrder());
order.OrderType = POOrderType.RegularOrder; // This is the default so not necessary
order.OrderDesc = "some text";
order.EmployeeID = 215;
order.Hold = false;
order.VendorID = 79;
graph.Document.Update(order);
graph.Actions.PressSave();
throw new PXRedirectRequiredException(graph, null);
}
Using the Document view in place of the CurrentDocument view which is based on the current record of Document. Document is the primary view and the primary view should be used.
Also for the purchase order type the attribute related to the list values should be used for the stored value of the database (vs what you had was the displayed list value). For example order.OrderType = POOrderType.RegularOrder. Also this is the default value for a PO so it is not necessary to set this value unless you want a different constant found in the POOrderType class.
I have an appointment entity which has an association with contact entity. I am trying to remove all association from this appointment entity without explicitly providing contact_id. Here is my code snippet with create appointment entity and then associate with an existing contact.
Entity activity = new Entity("appointment");
activity["scheduledstart"] = DateTime.Now;
activity["scheduledend"] = DateTime.Now.AddMinutes(30);
activity["subject"] = "Test Meeting";
activity["description"] = "Test Description";
activity["owneridname"] = "test_user";
activity["location"] = "Dallas";
EntityCollection attendees = new EntityCollection();
Entity attendee1 = new Entity("activityparty");
attendee1["addressused"] = "test.test#acmegroup.com";
attendees.Entities.Add(attendee1);
activity["requiredattendees"] = attendees;
Guid id = _service.Create(activity);
Console.WriteLine("id: " + id);
AssociateRequest associateRequest = new AssociateRequest();
associateRequest.Relationship = new Relationship("new_appointment_contact");
associateRequest.Target = new Microsoft.Xrm.Sdk.EntityReference("appointment", id);
EntityReferenceCollection referenceCollection = new EntityReferenceCollection();
Microsoft.Xrm.Sdk.EntityReference entityReference = new Microsoft.Xrm.Sdk.EntityReference("contact", new Guid("e6e71e53-b44b-e211-a81e-0050568b36bf"));
referenceCollection.Add(entityReference);
associateRequest.RelatedEntities = referenceCollection;
// Execute the request.
_service.Execute(associateRequest);
I am aware of using DisassociateRequest to remove this association but I don't want to explicitly provide contact_id. I just need something like .Clear() which can
remove all contact association.
DisassociateRequest disassociateRequest = new DisassociateRequest();
disassociateRequest.Relationship = new Relationship("new_appointment_contact");
disassociateRequest.Target = new Microsoft.Xrm.Sdk.EntityReference("appointment", id);
EntityReferenceCollection referenceCollection2 = new EntityReferenceCollection();
Microsoft.Xrm.Sdk.EntityReference entityReference2 = new Microsoft.Xrm.Sdk.EntityReference("contact", new Guid("e6e71e53-b44b-e211-a81e-0050568b36bf"));
referenceCollection2.Add(entityReference2);
disassociateRequest.RelatedEntities = referenceCollection2;
// Execute the request.
_service.Execute(disassociateRequest);
I used GetRelatedEntities method to pull all related entities into collection and then use this collection to disassociate all related entities:
DisassociateRequest disassociateRequest = new DisassociateRequest();
disassociateRequest.Relationship = new Relationship("new_appointment_contact");
disassociateRequest.Target = new Microsoft.Xrm.Sdk.EntityReference("appointment", id);
EntityReferenceCollection referenceCollection2 = new EntityReferenceCollection();
Entity existingAppointment = _service.Retrieve("appointment", id, new ColumnSet(true));
foreach (Entity item in existingAppointment.GetRelatedEntities(orgContext, "new_appointment_contact"))
{
Guid contactId = new Guid(item["contactid"].ToString());
Microsoft.Xrm.Sdk.EntityReference entityReference2 = new Microsoft.Xrm.Sdk.EntityReference("contact", contactId);
referenceCollection2.Add(entityReference2);
}
disassociateRequest.RelatedEntities = referenceCollection2;
_service.Execute(disassociateRequest);
I have multiple entities to be stored in the same physical Azure table. I'm trying to Insert/Merge the table entries from a file. I'm trying to find a way to do this w/o really serializing each property or for that matter creating a custom entities.
While trying the following code, I thought maybe I could use generic DynamicTableEntity. However, I'm not sure if it helps in an insert operation (most documentation is for replace/merge operations).
The error I get is
HResult=-2146233088
Message=Unexpected response code for operation : 0
Source=Microsoft.WindowsAzure.Storage
Any help is appreciated.
Here's an excerpt of my code
_tableClient = storageAccount.CreateCloudTableClient();
_table = _tableClient.GetTableReference("CloudlyPilot");
_table.CreateIfNotExists();
TableBatchOperation batch = new TableBatchOperation();
....
foreach (var pkGroup in result.Elements("PartitionGroup"))
{
foreach (var entity in pkGroup.Elements())
{
DynamicTableEntity tableEntity = new DynamicTableEntity();
string partitionKey = entity.Elements("PartitionKey").FirstOrDefault().Value;
string rowKey = entity.Elements("RowKey").FirstOrDefault().Value;
Dictionary<string, EntityProperty> props = new Dictionary<string, EntityProperty>();
//if (pkGroup.Attribute("name").Value == "CloudServices Page")
//{
// tableEntity = new CloudServicesGroupEntity (partitionKey, rowKey);
//}
//else
//{
// tableEntity = new CloudServiceDetailsEntity(partitionKey,rowKey);
//}
foreach (var element in entity.Elements())
{
tableEntity.Properties[element.Name.ToString()] = new EntityProperty(element.Value.ToString());
}
tableEntity.ETag = Guid.NewGuid().ToString();
tableEntity.Timestamp = new DateTimeOffset(DateTime.Now.ToUniversalTime());
//tableEntity.WriteEntity(/*WHERE TO GET AN OPERATION CONTEXT FROM?*/)
batch.InsertOrMerge(tableEntity);
}
_table.ExecuteBatch(batch);
batch.Clear();
}
Have you tried using DictionaryTableEntity? This class allows you to dynamically fill the entity as if it were a dictionary (similar to DynamicTableEntity). I tried something like your code and it works:
var batch = new TableBatchOperation();
var entity1 = new DictionaryTableEntity();
entity1.PartitionKey = "abc";
entity1.RowKey = Guid.NewGuid().ToString();
entity1.Add("name", "Steve");
batch.InsertOrMerge(entity1);
var entity2 = new DictionaryTableEntity();
entity2.PartitionKey = "abc";
entity2.RowKey = Guid.NewGuid().ToString();
entity2.Add("name", "Scott");
batch.InsertOrMerge(entity2);
table.ExecuteBatch(batch);
var entities = table.ExecuteQuery<DictionaryTableEntity>(new TableQuery<DictionaryTableEntity>());
One last thing, I see that you're setting the Timestamp and ETag yourself. Remove these two lines and try again.
public List<EmployeeDirectory> employee = new Health_Scheme_SystemDB.Select
.From<EmployeeDirectory>()
.Where(EmployeeDirectoryTable.ID_NOColumn).Contains(1005)
.ExecuteTypedList<EmployeeDirectory>();
The .Select is giving me problems. Its saying that 'Health_Scheme_System.Health_Scheme_SystemDB.Select' is a 'property' but is used like a 'type'
Remove the new - you are not creating a new instance so you shouldn't use new.
public List<EmployeesX> GetID(string IDNO)
{
Health_Scheme_System.Health_Scheme_SystemDB db = new Health_Scheme_System.Health_Scheme_SystemDB();
var d = (from c in db.EmployeeDirectories
where c.ID_NO.Contains(IDNO)
select new EmployeesX { ID_NO = c.ID_NO, FIRST_NAME = c.FIRST_NAME, LAST_NAME = c.LAST_NAME, EMPLOYMENT_DATE = ((DateTime)c.EMPLOYMENT_DATE).Date, TERMINATION_DATE = ((DateTime)c.TERMINATION_DATE).Date, LOCATION_CODE = c.LOCATION_CODE });
return d.ToList<EmployeesX>();
}
Then bind the grid view with this code. obviously there the data input in the textbox only will be displayed in the gridview.
gvView.DataSource = da.GetID(txtIDNO.Text);
gvView.DataBind();
I am using the code below to update a second table (Info2) with the identity used from the first table (info2.Id = info.Id;). When the second save is carried out (info2.Save()) I get the error: "There is already an open DataReader associated with this Command which must be closed first.".
Can anyone see what I may be doing wrong.
SubSonic version 3.0.0.3 and SQL Server 2005
Thanks
using (SharedDbConnectionScope sharedConnectionScope = new SharedDbConnectionScope())
{
using (TransactionScope ts = new TransactionScope())
{
Info info = new Info();
info.Desc = "Some information";
info.Save();
Info2 info2 = new Info2();
info2.Id = info.Id;
info2.Desc = "More information";
info2.Save();
ts.Complete();
}
}
Looks like you've got the TransactionScope and the SharedDbConnectionScope the wrong way round, try:
using (TransactionScope ts = new TransactionScope())
{
using (SharedDbConnectionScope sharedConnectionScope = new SharedDbConnectionScope())
{
Info info = new Info();
info.Desc = "Some information";
info.Save();
Info2 info2 = new Info2();
info2.Id = info.Id;
info2.Desc = "More information";
info2.Save();
ts.Complete();
}
}
As per what I have written in the comments, the only way I can get this working is using TransactionScope first then SharedDbConnectionScope (thanks Adam) and to add MultipleActiveResultSets=True; (SQL Server 2005) to the connection string.
Anybody have any better solutions or other suggestions?
Thanks
try
{
using (TransactionScope ts = new TransactionScope())
{
using (SharedDbConnectionScope scs = new SharedDbConnectionScope())
{
Info info = new Info();
info.Desc = "Some information";
info.Save();
//Test for rollback
//throw new Exception("STOP");
Info2 info2 = new Info2();
info2.Id = info.Id;
info2.Desc = "More information";
info2.Save();
ts.Complete();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}