I have a class that I wrote that saves and retrieves any objects to a windows phone isolated storage system. Have a look...
public class DataCache
{
// Method to store an object to phone ************************************
public void StoreToPhone(string key, Object objectToStore)
{
var settings = IsolatedStorageSettings.ApplicationSettings;
try
{
if (existsInStorage(key))
{
settings.Remove(key);
settings.Add(key, objectToStore);
}
else
{
settings.Add(key, objectToStore);
}
}
catch (Exception e)
{
MessageBox.Show("An error occured while trying to cache data: " + e.Message);
}
}
// Method to retrieve an object ******************************************
public Object retrieveFromPhone(string key)
{
var settings = IsolatedStorageSettings.ApplicationSettings;
Object retrievedObject = null;
try
{
if (existsInStorage(key))
{
settings.TryGetValue<Object>(key, out retrievedObject);
}
else
{
MessageBox.Show(string.Format("Cannot find key {0} in isolated storage", key));
}
}
catch(Exception e)
{
MessageBox.Show("An error occured while trying to retrieve cache object: "+e.Message);
}
return retrievedObject;
}
// Helper method to check if there is space on the phone to cache the data
private bool IsSpaceAvailable(long spaceReq)
{
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
long spaceAvail = store.AvailableFreeSpace;
if (spaceReq > spaceAvail)
{
return false;
}
return true;
}
}
// Method to check if key exists in isolated storage *********************
public bool existsInStorage(string key)
{
var settings = IsolatedStorageSettings.ApplicationSettings;
bool objectExistsInStorage = settings.Contains(key);
return objectExistsInStorage;
}
}
When I run my app and try and store some data using my StoreToPhone() method I get the following error:
An error occurred while trying to cache data: Value does not fall within the expected range
I don't exactly know what this means.. Is it not expecting this type of object? I'm not sure... I'm passing it a custom class I wrote fyi.
Some times before I too ran into same problem.
It seems the error says 'there may be duplicate value in the storage'.
so i used 'remove' before 'add', and then also i found not everything was saved, so i used 'save' function after 'add'.
It worked for me...
IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;
appSettings.Remove("name");
appSettings.Add("name", "James Carter");
appSettings.Save();
tbResults.Text = (string)appSettings["name"];
Related
I have implemented the IM application (name is "ContactCardDesktop.exe") as suggested by the link https://msdn.microsoft.com/en-us/library/office/jj900715(v=office.15).aspx
I have done all the registry setting per the article. but there is no call to outlook to IM application for function GetAuthenticationInfo() and GetInterface().
Even not getting the ProcessID at registry location HKCU\Software\IM Providers\ContactCardDesktop.
In outlook logs I am getting errors attached below. I have gone through to many suggestion but didn't get help much.
Please suggest the problem/solution.
Sample code for Application.
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(_IUCOfficeIntegrationEvents))]
[ProgId("LitwareClientAppObject.Class")]
[Guid("449B04AD-32A8-4D21-B0AE-8FC316E051CE"), ComVisible(true)]
public partial class LitwareClientAppObject : IUCOfficeIntegration
{
IMClient imClient;
Automation imAutomation;
public LitwareClientAppObject()
{
InitializeComponent();
imClient = new IMClient();
imAutomation = new IMClientAutomation();
}
// Implementation details omitted.
public string GetAuthenticationInfo(string _version)
{
string supportedOfficeVersion = "15.0.0.0";
// Do a simple check for equivalency.
if (supportedOfficeVersion == _version)
{
return "<authenticationinfo>";
}
else
{
return null;
}
}
public object GetInterface(string _version, OIInterface _interface)
{
IMClient imClient = new IMClient();
IMClientAutomation imAutomation = new IMClientAutomation();
switch (_interface)
{
case OIInterface.oiInterfaceILyncClient:
{
return imClient;
}
case OIInterface.oiInterfaceIAutomation:
{
return imAutomation;
}
default:
{
throw new NotImplementedException();
}
}
}
public OIFeature GetSupportedFeatures(string _version)
{
OIFeature supportedFeature1 = OIFeature.oiFeatureQuickContacts;
OIFeature supportedFeature2 = OIFeature.oiFeatureFastSearch;
return (supportedFeature1 | supportedFeature2);
}
Errors like:
CMsoIMProviderFactory::HrEnsureDefaultIMAppRegKeys Succeeded opening reg key (HKCU:SOFTWARE\IM Providers)
CMsoIMProviderFactory::HrEnsureDefaultIMAppRegKeys Succeeded querying reg key (HKCU:SOFTWARE\IM Providers:DefaultIMApp:ContactCardDesktop)
CMsoIMProviderFactory::HrEnsureDefaultIMProcessRegKey Succeeded opening reg key (HKCU:SOFTWARE\IM Providers\ContactCardDesktop)
CMsoIMProviderFactory::HrEnsureDefaultIMProcessRegKey Succeeded opening reg key (HKLM:SOFTWARE\IM Providers\ContactCardDesktop)
CMsoIMProviderFactory::WhichMessengerInProcessList Using (ContactCardDesktop.exe) process name for search
CMsoIMProviderFactory::WhichMessengerInProcessList Using (ContactCardDesktop.exe) process name for search hr = 80040154, We couldn't identify the provider type we now try to manually CoCreate using the LCClient CLSID
CMsoIMProviderFactory::HrGetAvailableProvider !failed! Line: 409 hr = 0x80040154 hr = 80040154, We couldn't identify the provider type we now try to manually CoCreate using the LCClient CLSID
CMsoIMProviderFactory::HrGetAvailableProvider !failed! Line: 289 hr = 0x80004005 !!!Provider Initialization Failed!!!
I have solved this issue to use COM server "CSExeCOMServer" that is at https://code.msdn.microsoft.com/windowsapps/CSExeCOMServer-3b1c1054
I am using the Xi interface to retrieve data from an OPC .NET server. The issue that I am having though is that the server seems to be incorrectly identifying a parameter as not being historized.
Even though all the information from DeltaV indicates that the corresponding parameter for the ObjectAttributes object returned from the server should indicate that it is collecting history, the IsCollectingHistory property actually indicates that it is false.
History collection is enabled:
The parameter in question is in the history collection:
I won't include the screenshot but I can also open the historical trend for that parameter. But as you can see below, when I inspect the retrieved object while debugging, it says that it is not being historized.
Here is some of the code that I am using:
FindCriteria criteria = createCriteria(path, false);
List<Parameter> parameters = new List<Parameter>();
IEnumerable<ObjectAttributes> enumerableObject;
int i = 0;
try
{
enumerableObject = iContext.FindObjects(criteria, 50);
}
catch (System.ServiceModel.FaultException)
{
//This error is thrown when no data is returned.
return null;
}
A few lines down, I then do some object initialization for my Parameter object, assigning it the properteries from the object that was received from the server. It is not shown below but I then add my Parameter object to a collection if it is being historized. It never gets added to the collection because the IsCollectingHistory property is always false.
enumerableObject = enumerableObject.Skip(1);
foreach (ObjectAttributes oa in enumerableObject)
{
Parameter _parameter = new Parameter
{
IsHistorized = oa.IsCollectingHistory,
IsLeaf = oa.IsLeaf
};
//...
Any ideas on where I am going wrong?
Edit:
After trying MotteAndBailey's answer, an error is thrown at the call to AddNewDataObjectToDataJournalList. The message associated with it is "The OPC HDA Create Browse failed".
Below is a screenshot of the error in a message box when using HDAprobe:
Some info on properties in OPC.NET -
The Xi server wraps the OPCDA and OPCHDA servers. The item properties (attributes) available on each server and the means of accessing them using Classic (DCOM) OPC vary considerably.
OPCDA
The OPCDA server provides a method for determining item properties:
IOPCItemProperties::GetItemProperties()
This call provides the client with a way to read all an item’s attribute values using the item ID (string path for the item in the Server’s address space) and propertyID. The Xi server uses this call when performing a FindObjects() call. FindObjects() returns all the properties exposed by the OPCDA server for an item.
OPCHDA
The OPCHDA server has a method for determining item properties, but it requires the item handle not the ItemID/path:
IOPCHDA_SyncRead::ReadAttribute()
As a result, the FindObjects() call for an OPCHDA server through Xi only returns the item ID property. The other attributes are set to defaults. To determine what the actual values of the other properties are a user must add the item to a list and call ReadAttribute() on the specific property they wish to see.
In summary, the OPCDA server works pretty much like you would expect and returns the object properties in a single method call; however, the OPCHDA server requires an additional step to get all the object properties.
The sample code will produce an Xi Journal list with only the on-scan history items.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xi.Client.Base.API;
using Xi.Client.Base;
using Xi.Contracts;
using Xi.Contracts.Data;
using Xi.Contracts.Constants;
using System.ServiceModel.Description;
using Xi.Client.CommonDialogs;
using System.Runtime.Serialization;
namespace ConsoleFindObjectsHDA
{
public class DotNetSupport
{
IXiEndpointDiscovery iEndpointDiscovery;
IXiContext iContext;
IXiEndpointBase readEndpoint;
ServiceEndpoint RMSvcEndpt;
//the list of items the user is trying to read
IXiDataJournalList iDataJournalList;
public void GetSomeData()
{
//get a connection to an OPC.NET server
if (Connect())
{
//we have to have a list to add a tag to and hold returned datasets
if (CreateJournalList())
{
//now use the list to add items and read their attributes - only "good" ones will be left on the list
ListAllHDAItemsOnScan();
if (iDataJournalList.Count() > 0)
{
//at this point we <should> have a DataJournalList containing only the HDA items on scan
//we can use the normal data read methods to get history for the items if we wish
// <do some history thing here>
}
else
{
Console.WriteLine("\nThere were no points on-scan in the historian");
}
Console.WriteLine("\nPress <return> to exit program");
Console.ReadLine();
}
////clean up if we have open connections/contexts
Cleanup();
}
}
//we will use FindObjects to browse all the leaves in the HDA server, then add them one-by-one to a datalist
//when we query their on-scan property and it is true we leave them on the list
//...if not, we remove them (giving us a list of the good HDA points)
void ListAllHDAItemsOnScan()
{
FindCriteria criteria = GetLeafCriteria();
IEnumerable<ObjectAttributes> enumerableObject;
try
{
//ask the server for a list of leaves...up to 50 max returned in this call
enumerableObject = iContext.FindObjects(criteria, 50);
//for each string itemID: add it to the list, read the attribute, and remove it from the list if not on-scan
foreach (ObjectAttributes oa in enumerableObject)
{
//we do not have to commit this because we have indicated the operation is NOT prep-only
Console.WriteLine("Adding OPCHDA item {0}.", oa.InstanceId.LocalId);
IXiHistoricalDataObject ixObject = iDataJournalList.AddNewDataObjectToDataJournalList(oa.InstanceId, false);
//we are getting the CURRENT (from NOW -to- NOW) item status
FilterCriterion fc1 = GetFilterCriteriaDateTime(DateTime.Now);
//tell the server what property (attribute) we want to read
List<TypeId> lstp = new List<TypeId>();
TypeId typeit = new TypeId("", "", DVServerAttributes.DELTAV_DVCH_ON_SCAN.ToString());
lstp.Add(typeit);
//read the property from the server
iDataJournalList.ReadJournalDataProperties(fc1, fc1, ixObject, lstp);
//find the current item and check it for "on-scan"
if (ixObject != null)
{
if (ixObject.PropertyValues.First().PropertyValues.UintValues.First() == 1)
{
Console.WriteLine("OPCHDA item {0} is on-scan.\n", oa.InstanceId.LocalId);
}
else
{
if (ixObject.PrepForRemove())
{
Console.WriteLine("OPCHDA item {0} is not on-scan. Removing item.\n", oa.InstanceId.LocalId);
iDataJournalList.CommitRemoveableElements();
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception in FindObjects(). The exception is:{0}\n", ex.Message);
}
}
//create a filtercriterion for a specific date time - this is an EQUAL (not > or <) comparison operator
public FilterCriterion GetFilterCriteriaDateTime(DateTime dtChosenTime)
{
//simple timestamp filter which is used by the read call
FilterCriterion filterCriterion = null;
// this is a timestamp
string filterOperand = FilterOperandNames.Timestamp;
//make the given time with UTC/Local set to local time just to be sure
DateTime dtTmp1 = DateTime.SpecifyKind(dtChosenTime, DateTimeKind.Local);
object comparisonValue = dtTmp1;
//timestamp equal to this one
uint oper = FilterOperator.Equal;
//create the filter
filterCriterion = new FilterCriterion()
{
OperandName = filterOperand,
Operator = oper,
ComparisonValue = comparisonValue,
};
return filterCriterion;
}
//create a filtercriterion for leaves (OPCHDA items)
public FilterCriterion GetLeafFilterCriterion()
{
//simple filter for leaves
FilterCriterion filterCriterion = null;
// what this criterion applies to
string filterOperand = FilterOperandNames.BranchOrLeaf;
//Must equal "LEAF" to match
uint oper = FilterOperator.Equal;
//create the filter
filterCriterion = new FilterCriterion()
{
OperandName = filterOperand,
Operator = oper,
ComparisonValue = "LEAF",
};
return filterCriterion;
}
//set up the FindCriteria search of the server
public FindCriteria GetLeafCriteria()
{
FindCriteria findCriteria = null;
findCriteria = new FindCriteria();
//our browse starts at the root - NULL means "continue browsing from where you are"
findCriteria.StartingPath = new ObjectPath("//", "HDA");
//a list of OR-ed filter criteria (we have only one)
ORedFilters orthefilters = new ORedFilters();
//the FilterCriteria list (there is only one criterion)
orthefilters.FilterCriteria = new List<FilterCriterion>();
orthefilters.FilterCriteria.Add(GetLeafFilterCriterion()); //we want leaves
//add our OR-ed filter to the filterset filters list (whew!)
findCriteria.FilterSet = new FilterSet();
findCriteria.FilterSet.Filters = new List<ORedFilters>();
findCriteria.FilterSet.Filters.Add(orthefilters);
return findCriteria;
}
//connect to the OPC.NET server and get a read endpoint
public bool Connect()
{
//set this to point to your OPC.Net server
string serverUrl = "http://localhost:58080/XiServices/ServerDiscovery";
bool bReturnVal = false;
try
{
Console.WriteLine("Getting Endpoint Discovery from server:\n{0}\n", serverUrl);
//This class is used to locate a server and obtain its list of ServiceEndpoints.
iEndpointDiscovery = new XiEndpointDiscovery(serverUrl) as IXiEndpointDiscovery;
//we have the server...now check for endpoints
//there should always be TCP endpoints for a DeltaV OPC.NET server so we do not search HTTP and Named Pipes to find one
//and we do not consider choosing the fastest option between the three (TCP/HTTP/NamedPipes). We just use the TCP/IP one.
// GetServiceEndpointsByBinding searches the list of endpoints on the XiEndpointDiscovery connection with the specified contractType and binding type.
// We use the ResourceManagement endpoint to find the the other open endpoints on the server (some might be disabled)
IEnumerable<ServiceEndpoint> resourceEndpoints = iEndpointDiscovery.GetServiceEndpointsByBinding(typeof(IResourceManagement).Name, typeof(System.ServiceModel.NetTcpBinding));
//use the first (probably only) resource endpoint for TCP/IP to open a context between client and server
if ((resourceEndpoints != null) && (resourceEndpoints.Count() > 0))
{
var serviceEndpoints = resourceEndpoints as IList<ServiceEndpoint> ?? resourceEndpoints.ToList();
//pick the first RM endpoint we found
RMSvcEndpt = ((IList<ServiceEndpoint>)serviceEndpoints).First();
//Open the Context using the RM endpoint and some other values including timeout, what we want to read (HDA), and the GUID for this context
Console.WriteLine("Opening Client Context with Initiate\n");
iContext = XiContext.Initiate(RMSvcEndpt,
iEndpointDiscovery.ServerEntry,
300000,
(uint)ContextOptions.EnableJournalDataAccess, //HDA
(uint)System.Threading.Thread.CurrentThread.CurrentCulture.LCID,
Guid.NewGuid().ToString());
if (iContext != null)
{
//find a read endpoint using the XiEndpointDiscovery connection
IEnumerable<ServiceEndpoint> readseps = iEndpointDiscovery.GetServiceEndpointsByBinding(typeof(IRead).Name, RMSvcEndpt.Binding.GetType());
//if we found at least one read endpoint, connect the context to it
readEndpoint = null;
if (readseps != null)
{
Console.WriteLine("Adding Read endpoint to Context\n");
ServiceEndpoint sep = readseps.ElementAt<ServiceEndpoint>(0);
readEndpoint = iContext.OpenEndpoint(sep, 30000, new TimeSpan(5000));
if (readEndpoint != null)
{
bReturnVal = true; //everything went OK
}
else
{
Console.WriteLine("Unable to add Read endpoint to Context\n");
bReturnVal = false; //failed
}
}
}
else
{
Console.WriteLine("Unable to open Client Context\n");
bReturnVal = false;
}
}
}
catch (Exception)
{
bReturnVal = false;
}
return (bReturnVal);
}
public bool CreateJournalList()
{
bool retval = false;
try
{
//create a new list of HDA objects for this read
// update buffer
// rate rate filterset(not used here)
iDataJournalList = iContext.NewDataJournalList(1000, 1000, null);
if (iDataJournalList != null)
{
//we need to add the list to a read endpoint to give it data access
iDataJournalList.AddListToEndpoint(readEndpoint);
//enable the list so we can connect the items we add to it and read data
iDataJournalList.EnableListUpdating(true);
retval = true;
}
}
catch (Exception)
{
retval = false;
}
return retval;
}
public void Cleanup()
{
if (iContext != null)
{
iContext.Dispose();
}
}
} //class DotNetSupport
}
namespace ConsoleFindObjectsHDA
{
public class DVServerAttributes
{
//some DeltaV-specific OPCHDA attributes
public static uint DELTAV_DESC = 2147483650;
public static uint DELTAV_ENG_UNITS = 2147483651;
public static uint DELTAV_EU100 = 2147483666;
public static uint DELTAV_EU0 = 2147483667;
public static uint DELTAV_DVCH_LAST_DOWNLOAD = 2147483682;
public static uint DELTAV_DVCH_ON_SCAN = 2147483683;
public static uint DELTAV_NAMED_SET = 2147483698;
}
}
Steve Marx writes about new extension methods to perform upserts in Azure Table Storage as part of the new storage protocol version here:
http://blog.smarx.com/posts/extension-methods-for-the-august-storage-features
However, what if I want to do the original operation of unconditional-merge-or-throw, rather than an upsert. I want to merge an object, updating a single field, but throw if the entity doesn't exist rather than create a new entity that contains only the properties I'm merging.
Is this possible? Note that I want to use upsert elsewhere, so I've taken to having IoC provide me with contexts created from GetDataServiceContext2011 instead of GetDataServiceContext. I suppose I could alternate between the two, but that won't help when the Azure team updates the official libraries.
According to MSDN:
The Insert Or Merge Entity operation uses the MERGE verb and must be
called using the 2011-08-18 version or newer. In addition, it does not
use the If-Match header. These attributes distinguish this operation
from the Update Entity operation, though the request body is the same
for both operations.
So, how do I get the storage library to emit a wildcard If-Match on save rather than emit no If-Match at all?
Just use AttachTo with an asterisk for an etag. That will result in an If-Match: *. Here's a complete working example:
class Entity : TableServiceEntity
{
public string Text { get; set; }
public Entity() { }
public Entity(string rowkey) : base(string.Empty, rowkey) { }
}
class Program
{
static void Update(CloudStorageAccount account)
{
var ctx = account.CreateCloudTableClient().GetDataServiceContext();
var entity = new Entity("foo") { Text = "bar" };
ctx.AttachTo("testtable", entity, "*");
ctx.UpdateObject(entity);
ctx.SaveChangesWithRetries();
}
static void Main(string[] args)
{
var account = CloudStorageAccount.Parse(args[0]);
var tables = account.CreateCloudTableClient();
tables.CreateTableIfNotExist("testtable");
var ctx = tables.GetDataServiceContext();
try { Update(account); } catch (Exception e) { Console.WriteLine("Exception (as expected): " + e.Message); }
ctx.AddObject("testtable", new Entity("foo") { Text = "foo" });
ctx.SaveChangesWithRetries();
try { Update(account); } catch (Exception e) { Console.WriteLine("Unexpected exception: " + e.Message); }
Console.WriteLine("Now text is: " + tables.GetDataServiceContext().CreateQuery<Entity>("testtable").Where(e => e.PartitionKey == string.Empty && e.RowKey == "foo").Single().Text);
tables.DeleteTableIfExist("testtable");
}
}
I'm having an issue when trying to programmatically update a DateTime field that already has a date stored in it.
The error that i'm getting is:
System.InvalidOperationException: There was an error generating the XML document. ---> System.ArgumentException: Value of type 'CrmDateTimeProperty' is not supported.
Parameter name: value
This is the code that performs the CRM update:
public bool UpdatePromptList(PromptList list)
{
DynamicEntity c = crmService.RetrieveDynamicEntity("ntup1_promptlist", list.PromptListId);
if (c != null)
{
c.UpdateBoolean("examplebooleanfield", list.booleanField);
c.UpdateDateTime("exampledatefield", list.dateField);
c.UpdateString("examplestringfield", list.stringField);
try
{
crmService.Update(c);
}
catch (SoapException)
{
return false;
}
}
}
And here is the code that validates the DateTime value to be passed into CRM:
public static CrmDateTime FromUser(DateTime userTime)
{
return new CrmDateTime(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:s}", userTime));
}
public static void UpdateDateTime(this DynamicEntity entity, string property, DateTime? date)
{
if (date == null)
{
if (entity.Properties.Contains(property))
{
entity.Properties.Remove(property);
}
return;
}
CrmDateTime crmDate = FromUser(date.Value);
CrmDateTimeProperty crmProp = new CrmDateTimeProperty(property, crmDate);
if (entity.Properties.Contains(property))
{
entity.Properties[property] = crmProp;
}
else
{
entity.Properties.Add(crmProp);
}
}
Any help on this would be greatly appreciated.
If you want to update the date when it is null you should alter your update method to not drop the property if it is null, but instead null it out, otherwise no update will occur for that attribute -
CrmDateTime myDateTime = new CrmDateTime();
myDateTime.IsNull = true;
myDateTime.IsNullSpecified = true;
It looks like your error is occurring because you are setting the property value to a CrmDateTimeProperty when it expects a CrmDateTime.
Change this -
if (entity.Properties.Contains(property))
{
entity.Properties[property] = crmProp;
}
to this -
if (entity.Properties.Contains(property))
{
entity.Properties[property] = crmDate;
}
and that should solve the issue you are running into.
I'm tryring to do a simple insert with foreign key, but it seems that I need to use db.SaveChanges() for every record insert. How can I manage to use only one db.SaveChanges() at the end of this program?
public static void Test()
{
using (var entities = new DBEntities())
{
var sale =
new SalesFeed
{
SaleName = "Stuff...",
};
entities.AddToSalesFeedSet(sale);
var phone =
new CustomerPhone
{
CreationDate = DateTime.UtcNow,
sales_feeds = sale
};
entities.AddToCustomerPhoneSet(phone);
entities.SaveChanges();
}
}
After running the above code I get this exception:
System.Data.UpdateException: An error occurred while updating the entries. See the InnerException for details. The specified value is not an instance of a valid constant type
Parameter name: value.
EDIT: Changed example code and added returned exception.
Apperantly using UNSIGNED BIGINT causes this problem. When I switched to SIGNED BIGINT everything worked as it supposed to.
I tried to do this "the right way":
And then I wrote this little test app to scan a directory, store the directory and all its files in two tables:
static void Main(string[] args)
{
string directoryName = args[0];
if(!Directory.Exists(directoryName))
{
Console.WriteLine("ERROR: Directory '{0}' does not exist!", directoryName);
return;
}
using (testEntities entities = new testEntities())
{
StoredDir dir = new StoredDir{ DirName = directoryName };
entities.AddToStoredDirSet(dir);
foreach (string filename in Directory.GetFiles(directoryName))
{
StoredFile stFile = new StoredFile { FileName = Path.GetFileName(filename), Directory = dir };
entities.AddToStoredFileSet(stFile);
}
try
{
entities.SaveChanges();
}
catch(Exception exc)
{
string message = exc.GetType().FullName + ": " + exc.Message;
}
}
}
As you can see, I only have a single call to .SaveChanges() at the very end - this works like a charm, everything's as expected.
Something about your approach must be screwing up the EF system.....
it might be related with the implementation of AddToSalesFeedSet etc..
there is chance that you are doing commit inside ?
any way, my point is that i encountered very close problem, was tring to add relation to new entity with existed entity that been queried earlier - that has unsigned key
and got the same exception;
the solution was to call Db.collection.Attach(previouslyQueriedEntityInstance);