retrieve the Quote Detail with c# - visual-studio-2010

I'm trying to create a custom workflow (for Dynamics CRM 2011) which must send an email with information on the Details Quote from a quote.
I create it in Visual Studio 2010 with the sdk.
The workflow is triggered manualy from a quote.
I am able to retrieve the value of the customerid, but I am unable to get the attached documents or the quotedetails of the Quote, when I launched the workflow I have this exception :
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Microsoft.Xrm.Sdk.Entity.get_Item(String attributeName)
at CPageCRM.Workflow.QuoteSendMailNotificationRIP.Execute(CodeActivityContext executionContext)
My code is :
//to get the current Quote
Entity preImageEntity = context.PreEntityImages.Values.FirstOrDefault();
//preImageEntity is a Quote because I trigger the workflow from a Quote
//the next two lines work, I can retrieve the good value of the Quote
string natureDevis = Utils.GetOptionSetValueLabel(service, preImageEntity, "new_nature", (OptionSetValue)preImageEntity["new_nature"]);
string prospectDevis = ((EntityReference)preImageEntity["customerid"]).Name;
//I get the exception after that :
List<QuoteDetail> listQuoteDetail = new List<QuoteDetail>();
listQuoteDetail = preImageEntity["quote_details"] as List<QuoteDetail>; //I get the exception
I don't understand why the quote_details doesn't exist in the dictionnary, because when I do :
Quote devis = new Quote();
devis.quote_details //<= (the autocompletion is working)
I have the same problem when I try to get sharepointdocumentlocation
Anyone have an explication? How can I retrieve the Quote Details and the document attached to my Quote from the code?
Thanks

A comment and potential answer.
My comment is when retrieving stuff out of the Images I often find it easier to let the compiler grab the proper type and just use 'var'.
My answer is that quote_details isn't just a field, but an actual 1-n relationshp (by looking in the metadata browser). You may need to get the related entities in a separate retrieve.
Edit:
For example: _service.Retrieve("quote", quoteId, new ColumnSet("quote_details"))
will retrieve the quote details from the service. However, you could also check and see if you are passing in the quote_details attribute from the PreImage.

I successed with a linq query
I had to search the quote_detail which were linked to the quote :
var queryQuoteDetail = from r in orgServiceContext.CreateQuery("quotedetail")
where ((EntityReference)r["quoteid"]).Id.Equals(context.PrimaryEntityId)
select r;

Related

Invalid Named Property

We call the microsoft exchange to set the extended property which in our case is an unique guid
microsoft.exchange.webservices.data.core.exception.service.remote.ServiceResponseException: An internal server error occurred. The operation failed., Invalid named property
Its been working great until now when some of our users are facing the above issue ....
val uId = getUniqueId();
val emailExtendedPropDef = new ExtendedPropertyDefinition(uId,"uniqueId", MapiPropertyType.String)
try {
email.setExtendedProperty(emailExtendedPropDef, uId.toString)
email.sendAndSaveCopy()
} catch {
case e: Exception =>
error(s"Exception in setting extended property for user $from", e)
throw e
}
trying to find the root cause of the issue, we are also thinking it might be related to throttling on Microsoft exchange for extended properties (Not sure how to prove if it's indeed throttling) any help to point us in the right direction will be of great help
Our use case is to able to retrieve the email when customer want's to reply back we want to retrieve that particular email to be included in users reply....currently we are using the uid to achieve that ....
we have been using the code as per the documentation here
https://learn.microsoft.com/en-us/previous-versions/office/developer/exchange-server-2010/dd633654(v%3Dexchg.80)
and also the documentation here
https://github.com/OfficeDev/ews-java-api/wiki/Getting-Started-Guide#extended-properties
Update : As per the comments we do understand that we have to treat extendedProperty as a column definition and update the same column ...but we couldn't figure out how to achieve this as...Any code samples to point us in the right direction will be of great help
Latest Update : We have deleted some of the extendedPropertyDefinition's but still facing the same invalid property could some one please point us in the right direction
Is it safe to say that getUniqueId returns a different guid on each call? If so, then that is the problem. Think of the Guid for an extended prop as a namespace. The exchange store limits the number of custom extended props to something like 32k per mailbox. So you are likely hitting that limit. But aside from that, the main reason for creating an extended property is so that you can refer to it later. But if you are basically discarding the namespace each time, you are leaving orphaned props on items. Without understanding your particular scenario, I can only say that the Guid should be thought of truly as a namespace. Choose one for your app/company/scenario and hard code it. They create all the named props you want within that namespace. For instance, "MyProp/String" in Guid namespace 1 is a different property than "MyProp/String" in Guid namespace 2.

Field returns empty string

I create a new profile document with the following code:
Set doc = db.Createdocument()
doc.Form = "SMBPrivateProfile"
Call doc.Computewithform(True,True)
Call doc.Save(True, False)
But whenever I want to read a field by #GetProfileField i get an empty string, even if the field I want to read has a default value.
After opening & saving the document manually everything works.
Further details:
I improved an application and hit Application --> Replace Design.... The new version includes a new field within the profile document. When reading one of these new fields, the result is an empty string. When reading an 'old' field within the same document the result is the expected string.
e.g.:
MessageBox([OK];"Title"; #GetProfileField("SMBPrivateProfile"; "OLD_FIELD"; #ThisName))
--> Will result in: "This is a fancy old default value"
MessageBox([OK];"Title"; #GetProfileField("SMBPrivateProfile"; "NEW_FIELD"; #ThisName))
--> Will result in: "" (instead of "This is a fancy new default value")
That's not a profile document. To create profile document use:
db.GetProfileDocument("SMBPrivateProfile");
You can also add a second parameter for a unique key in addition to profile name.
Also consider if you really want to use profile documents. They are heavily cached and not visible in any views.
If I'm reading you right, it appears that you have updated a form and added a new field with a default value formula. You are then reading an existing document. When you do this, the new field that you added to the form does not yet exist. New fields and formulas aren't applied to existing documents until you do something to force them to be applied.
If it's a regular document (as your original code indicated), you can just open the document in the Notes client, edit, and re-save it. That will create the NEW_FIELD and give it its value. If there are lots of these documents, you could write a simple formula agent to do this via #Command([ToolsRefreshAllDocs]) or #Command( [ToolsRefreshSelectedDocs]).
If it is a profile document (as per the responce chain to #Panu's anser), then after you do the replace design you will have to write an agent to open the existing profile document using db.getProfileDocument use doc.ReplaceItemValue("NEW_FIELD";"new value").

Create SharePoint IF function Workflow

I am trying to update the date in a column based on the information contained in another column. I know it will be an "IF" function, but I am not getting the formula correct.
I need to update the due date column by adding the time based from the frequency columnn(week, day, month, etc...) to the completion date column....please help!
I would not use the Designer inside Visual Studio to handle an If-Clause. Reason: I didn't figure out how to use this and from other things lieke the While-Activity I read that this is much slower than a coded one.
For some handsome looking I would add "CodeActivity" and link/ invoke my method to this. Inside this method you could use
string frequency = workflowProperties.Item["name of other column"].ToString();
string oldDate = workflowProperties.Item["name of updating column"].ToString();
DateTime newDate = Convert.ToDateTime(oldDate);
if (String.Equals(frequency, "weekly", StringComparison.OrdinalIgnoreCase))
{
<your code like:> workflowProperties.Item["name of updating column"] = newDate.AddDays(7);
}
else if (...)
or use switch (frequency){}
Remind that workflowProperties.Item refers everytime to selected Item. Because this is a global variable inside your workflow, you can access to it from every method. If you don't understand this example, be free to ask.
Shegit

Find account GUID, and Select it back using Object GUID

I am trying to select a unique identifiers for accounts from Active Directory. I found that "objectguid" attribute do identify a user uniquely, but my problem is that I don't know how to convert the retrieved value into a readable format. And then be able to select a user back using this value.
I am using spring ldap libraries, right now the "objectguid" return a char[] (15 element)
So, Does any one knows any thing that can help?
(Note, I can't use SAM Name attribute)
Thanks,
See here. It appears there are two string formats: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, which you can get via new BigInteger(0, (byte[])attr.get()).toString(16), and XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, which is the same thing plus punctuation.

Debugging LINQ to SQL SubmitChanges()

I am having a really hard time attempting to debug LINQ to SQL and submitting changes.
I have been using http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx, which works great for debugging simple queries.
I'm working in the DataContext Class for my project with the following snippet from my application:
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.SubmitChanges();
I will catch some very odd exceptions when I run this.SubmitChanges;
Index was outside the bounds of the array.
The stack trace goes places I cannot step into:
at System.Data.Linq.IdentityManager.StandardIdentityManager.MultiKeyManager`3.TryCreateKeyFromValues(Object[] values, MultiKey`2& k)
at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache`2.Find(Object[] keyValues)
at System.Data.Linq.IdentityManager.StandardIdentityManager.Find(MetaType type, Object[] keyValues)
at System.Data.Linq.CommonDataServices.GetCachedObject(MetaType type, Object[] keyValues)
at System.Data.Linq.ChangeProcessor.GetOtherItem(MetaAssociation assoc, Object instance)
at System.Data.Linq.ChangeProcessor.BuildEdgeMaps()
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
at JobTrakDataContext.CreateNewJob(NewJob job, String userName) in D:\JobTrakDataContext.cs:line 1119
Does anyone have any tools or techniques they use? Am I missing something simple?
EDIT:
I've setup .net debugging using Slace's suggestion, however the .net 3.5 code is not yet available: http://referencesource.microsoft.com/netframework.aspx
EDIT2:
I've changed to InsertOnSubmit as per sirrocco's suggestion, still getting the same error.
EDIT3:
I've implemented Sam's suggestions trying to log the SQL generated and to catch the ChangeExceptoinException. These suggestions do not shed any more light, I'm never actually getting to generate SQL when my exception is being thrown.
EDIT4:
I found an answer that works for me below. Its just a theory but it has fixed my current issue.
I always found useful to know exactly what changes are being sent to the DataContext in the SubmitChanges() method.
I use the DataContext.GetChangeSet() method, it returns a ChangeSet object instance that holds 3 read-only IList's of objects which have either been added, modified, or removed.
You can place a breakpoint just before the SubmitChanges method call, and add a Watch (or Quick Watch) containing:
ctx.GetChangeSet();
Where ctx is the current instance of your DataContext, and then you'll be able to track all the changes that will be effective on the SubmitChanges call.
First, thanks everyone for the help, I finally found it.
The solution was to drop the .dbml file from the project, add a blank .dbml file and repopulate it with the tables needed for my project from the 'Server Explorer'.
I noticed a couple of things while I was doing this:
There are a few tables in the system named with two words and a space in between the words, i.e. 'Job Master'. When I was pulling that table back into the .dbml file it would create a table called 'Job_Master', it would replace the space with an underscore.
In the orginal .dbml file one of my developers had gone through the .dbml file and removed all of the underscores, thus 'Job_Master' would become 'JobMaster' in the .dbml file. In code we could then refer to the table in a more, for us, standard naming convention.
My theory is that somewhere, the translation from 'JobMaster' to 'Job Master' while was lost while doing the projection, and I kept coming up with the array out of bounds error.
It is only a theory. If someone can better explain it I would love to have a concrete answer here.
My first debugging action would be to look at the generated SQL:
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.Log = Console.Out; // prints the SQL to the debug console
this.SubmitChanges();
The second would be to capture the ChangeConflictException and have a look at the details of failure.
catch (ChangeConflictException e)
{
Console.WriteLine("Optimistic concurrency error.");
Console.WriteLine(e.Message);
Console.ReadLine();
foreach (ObjectChangeConflict occ in db.ChangeConflicts)
{
MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType());
Customer entityInConflict = (Customer)occ.Object;
Console.WriteLine("Table name: {0}", metatable.TableName);
Console.Write("Customer ID: ");
Console.WriteLine(entityInConflict.CustomerID);
foreach (MemberChangeConflict mcc in occ.MemberConflicts)
{
object currVal = mcc.CurrentValue;
object origVal = mcc.OriginalValue;
object databaseVal = mcc.DatabaseValue;
MemberInfo mi = mcc.Member;
Console.WriteLine("Member: {0}", mi.Name);
Console.WriteLine("current value: {0}", currVal);
Console.WriteLine("original value: {0}", origVal);
Console.WriteLine("database value: {0}", databaseVal);
}
}
}
You can create a partial class for your DataContext and use the Created or what have you partial method to setup the log to the console.out wrapped in an #if DEBUG.. this will help you to see the queries executed while debugging any instance of the datacontext you are using.
I have found this useful while debugging LINQ to SQL exceptions..
partial void OnCreated()
{
#if DEBUG
this.Log = Console.Out;
#endif
}
The error you are referring to above is usually caused by associations pointing in the wrong direction. This happens very easily when manually adding associations to the designer since the association arrows in the L2S designer point backwards when compared to data modelling tools.
It would be nice if they threw a more descriptive exception, and maybe they will in a future version. (Damien / Matt...?)
This is what I did
...
var builder = new StringBuilder();
try
{
context.Log = new StringWriter(builder);
context.MY_TABLE.InsertAllOnSubmit(someData);
context.SubmitChanges();
}
finally
{
Log.InfoFormat("Some meaningful message here... ={0}", builder);
}
A simple solution could be to run a trace on your database and inspect the queries run against it - filtered ofcourse to sort out other applications etc. accessing the database.
That ofcourse only helps once you get past the exceptions...
VS 2008 has the ability to debug though the .NET framework (http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx)
This is probably your best bet, you can see what's happening and what all the properties are at the exact point in time
Why do you do UpdateJobMaster on a new instance ? Shouldn't it be InsertOnSubmit ?
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.InsertOnSubmit(newJobToCreate);
this.SubmitChanges();
This almost certainly won't be everyone's root cause, but I encountered this exact same exception in my project - and found that the root cause was that an exception was being thrown during construction of an entity class. Oddly, the true exception is "lost" and instead manifests as an ArgumentOutOfRange exception originating at the iterator of the Linq statement that retrieves the object/s.
If you are receiving this error and you have introduced OnCreated or OnLoaded methods on your POCOs, try stepping through those methods.
Hrm.
Taking a WAG (Wild Ass Guess), it looks to me like LINQ - SQL is trying to find an object with an id that doesn't exist, based somehow on the creation of the JobMaster class. Are there foreign keys related to that table such that LINQ to SQL would attempt to fetch an instance of a class, which may not exist? You seem to be setting the ProjectID of the new object to a string - do you really have an id that's a string? If you're trying to set it to a new project, you'll need to create a new project and get its id.
Lastly, what does UpdateJobMaster do? Could it be doing something such that the above would apply?
We have actually stopped using the Linq to SQL designer for our large projects and this problem is one of the main reasons. We also change a lot of the default values for names, data types and relationships and every once in a while the designer would lose those changes. I never did find an exact reason, and I can't reliably reproduce it.
That, along with the other limitations caused us to drop the designer and design the classes by hand. After we got used to the patterns, it is actually easier than using the designer.
I posted a similar question earlier today here: Strange LINQ Exception (Index out of bounds).
It's a different use case - where this bug happens during a SubmitChanges(), mine happens during a simple query, but it is also an Index out of range error.
Cross posting in this question in case the combination of data in the questions helps a good Samaritan answer either :)
Check that all the "primary key" columns in your dbml actually relate to the primary keys on the database tables. I just had a situation where the designer decided to put an extra PK column in the dbml, which meant LINQ to SQL couldn't find both sides of a foreign key when saving.
I recently encountered the same issue: what I did was
Proce proces = unit.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
where pt.Name == "Fix-O"
select pt).Single().ProcesTypeId &&
u.UnitId == UnitId);
Instead of:
Proce proces = context.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
where pt.Name == "Fix-O"
select pt).Single().ProcesTypeId &&
u.UnitId == UnitId);
Where context was obviously the DataContext object and "unit" an instance of Unit object, a Data Class from a dbml file.
Next, I used the "proce" object to set a property in an instance of another Data Class object. Probably the LINQ engine could not check whether the property I was setting from the "proce" object, was allowed in the INSERT command that was going to have to be created by LINQ to add the other Data Class object to the database.
I had the same non speaking error.
I had a foreign key relation to a column of a table that was not the primary key of the table, but a unique column.
When I changed the unique column to be the primary key of the table the problem went away.
Hope this helps anyone!
Posted my experiences with this exception in an answer to SO# 237415
I ended up on this question when trying to debug my LINQ ChangeConflictException. In the end I realized the problem was that I manually added a property to a table in my DBML file, but I forgot to set the properties like Nullable (should have been true in my case) and Server Data Type
Hope this helps someone.
This is a long time ago, but I had the same problem and the error was because of a trigger with a select statement. Something like
CREATE TRIGGER NAME ON TABLE1 AFTER UPDATE AS SELECT table1.key from table1
inner join inserted on table1.key = inserted.key
When linq-to-sql runs the update command, it also runs a select statement to receive the auto generated values in the same query and expecting the first record set to contains the columns "asked for" but in this case the first row was the columns from the select statement in the trigger. So linq-to-sql was expecting two autogenerated columns, but it only received one column (with wrong data) and that was causing this exception.

Resources