Vici coolstorage bug in saving ManyToMany pure relations? - many-to-many

We have a test case that creates a many-many relation between entities X and Y and then deletes the same relation.
SQLite throws a constraint violation that the relation exists. After digging a bit, we found that the relationship table still has an entry for the relationship.
It appears that this may be a bug in Vici CoolStorage itself. The code that handles removed and added objects looks like this (in CSListGeneric.cs):
if (Relation != null && Relation.PureManyToMany)
{
if (_removedObjects != null)
{
foreach (TObjectType obj in _removedObjects)
{
CSParameterCollection parameters = new CSParameterCollection();
parameters.Add("#LocalKey").Value = RelationObject.Data["#" + Relation.LocalKey].Value;
parameters.Add("#ForeignKey").Value = obj.Data["#" + Relation.ForeignKey].Value;
string deleteSql = DB.BuildDeleteSQL(Relation.LinkTable, null, DB.QuoteField(Relation.LocalLinkKey) + "=#LocalKey and " + DB.QuoteField(Relation.ForeignLinkKey) + "=#ForeignKey");
DB.ExecuteNonQuery(deleteSql, parameters);
}
_removedObjects = null;
}
if (_addedObjects != null)
{
foreach (TObjectType obj in _addedObjects)
{
CSParameterCollection parameters = new CSParameterCollection();
parameters.Add("#LocalKey").Value = RelationObject.Data["#" + Relation.LocalKey].Value;
parameters.Add("#ForeignKey").Value = obj.Data["#" + Relation.ForeignKey].Value;
DB.ExecuteInsert(Relation.LinkTable,
new[] { Relation.LocalLinkKey, Relation.ForeignLinkKey },
new[] { "#LocalKey", "#ForeignKey" },
null, null, null, parameters);
}
_addedObjects = null; // THIS WAS ADDED TO FIX THE BUG
}
Note that the removed objects collection is set to null after the delete statements are executed. However, the added objects collection is not similarly reset.
Adding the line at the bottom appears to fix the issue.
Is this the correct fix, or are we missing something?

Related

How to return Entity Data along with related Entities

Here is the structure:
And below is the code:
public IQueryable<PageTemplate> GetTemplate()
{
var PageTemplates = from oPT in _db.PageTemplates
join oHSFK in _db.HelperSites on oPT.SiteID equals oHSFK.SiteID into oHSChild
from oHS in oHSChild.DefaultIfEmpty()
join oHUFK in _db.HelperUsers on oPT.SiteID equals oHUFK.UserID into oHUChild
from oHU in oHUChild.DefaultIfEmpty()
where oPT.SiteID == ConfigDto.SiteDetails.SiteID || oPT.SiteID == null
select new
{
TemplateID = oPT.TemplateID,
TemplateName = oPT.TemplateName,
//SiteName = oHS.SiteName,
//UpdatedByName = oHU.UserFirstName + " " + oHU.UserLastName,
UpdatedDate = oPT.UpdatedDate
};
return null;
}
How do I return IQueryable<PageTemplate> which has related Entities already. I know the workaround of making a new class having all the required properties of PageTemplate, HelperSite & HelperUser classes. But, I am looking for a solution, if possible, to use existing Entity Framework classes.

How to use avro data with old and new namespace

I am facing a problem where I have updated the namespace in my avsc schema file. Since we were using common processor created in Java to parse the XML to avro and were using the avsc file.
We have separated the interfaces and created 2 different namespaces and now having 2 avsc schemas which are identical just the namespace is different.
Since we have data which was generated using old namespace, I am unable to query this data with new data generated with new namespace.
Here is example of my schemas -
Old schema - "type" : "record",
"name" : "Message",
"namespace" : "com.myfirstavsc",
"fields" : [ {
"name" : "Header",.....**other fields**
New schema - "type" : "record",
"name" : "Message",
"namespace" : "com.mysecondavsc",
"fields" : [ {
"name" : "Header",.....**other fields**
When I query my hive table I get below exception
Failed with exception java.io.IOException:org.apache.avro.AvroTypeException: Found com.myfirstavsc.Property, expecting union
I am not sure how you are trying to read your data but use GenericDatumReader should solve your issue, after that you can convert the generic record to your specific records. I found something similar here
http://apache-avro.679487.n3.nabble.com/Deserialize-with-different-schema-td4032782.html
http://apache-avro.679487.n3.nabble.com/Deserialize-with-different-schema-td4032782.html
The link mentioned above is not work anymore, so add an explanation here.
We got the same error in a project named Hudi, so raised an issue about it: https://github.com/apache/hudi/issues/7284
After trouble shooting, the root cause of this exception org.apache.avro.AvroTypeException: Found hoodie.test_mor_tab.test_mor_tab_record.new_test_col.fixed, expecting union is Avro schema generator rule, it can't accept the change of namespace when handling UNION type.
According to Avro Schema Resolution doc, it can accept schema evolution if either schema is a union in reader or writer schema in GenericDatumReader(Schema writer, Schema reader). But it didn't mention there is another restriction about it: the full name of schema must be the same if the type is RECORD or ENUM or FIXED.
Code reference:
ResolvingGrammarGenerator#bestBranch
public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
...
private int bestBranch(Schema r, Schema w, Map<LitS, Symbol> seen) throws IOException {
Schema.Type vt = w.getType();
// first scan for exact match
int j = 0;
int structureMatch = -1;
for (Schema b : r.getTypes()) {
if (vt == b.getType())
if (vt == Schema.Type.RECORD || vt == Schema.Type.ENUM ||
vt == Schema.Type.FIXED) {
String vname = w.getFullName();
String bname = b.getFullName();
// return immediately if the name matches exactly according to spec
if (vname != null && vname.equals(bname))
return j;
if (vt == Schema.Type.RECORD &&
!hasMatchError(resolveRecords(w, b, seen))) {
String vShortName = w.getName();
String bShortName = b.getName();
// use the first structure match or one where the name matches
if ((structureMatch < 0) ||
(vShortName != null && vShortName.equals(bShortName))) {
structureMatch = j;
}
}
} else
return j;
j++;
}
// if there is a record structure match, return it
if (structureMatch >= 0)
return structureMatch;
// then scan match via numeric promotion
j = 0;
for (Schema b : r.getTypes()) {
switch (vt) {
case INT:
switch (b.getType()) {
case LONG: case DOUBLE:
return j;
}
break;
case LONG:
case FLOAT:
switch (b.getType()) {
case DOUBLE:
return j;
}
break;
case STRING:
switch (b.getType()) {
case BYTES:
return j;
}
break;
case BYTES:
switch (b.getType()) {
case STRING:
return j;
}
break;
}
j++;
}
return -1;
}
...
}

Remove the isolated storage key/value pair on Application_Activated in wp8

In Application_Deactivated event, I am storing the data into IsolatedStorageSettings.ApplicationSettings as key/value pair.
In Application_Activated and Application_Closing events, I am removing the data from IsolatedStorageSettings.ApplicationSettings.
But when i check the isolated storage settings after removing the data, still the key/value pairs is exists.
I am pretty sure that i have removed the key/value pairs in Application_Activated and Application_Closing. I can see the debug line "deleted" printed.
And I am nowhere saving the data other than Application_Deactivated event.
please help me.. I am not getting where exactly its going wrong. how the data is still exists in isolatedstotage after removing ?
I am removing the data like below:
public void Remove(string token)
{
var store = IsolatedStorageSettings.ApplicationSettings;
if (token != null && store.Contains(token))
if (store.Remove(token) == true)
{
Debug.WriteLine("deleted after Remove " + token);
}
else
{
Debug.WriteLine("Not deleted after Remove " + token);
}
}
you have to save settings after removing key.
IsolatedStorageSettings.ApplicationSettings.Save();
Edited : in you case.
public void Remove(string token)
{
var store = IsolatedStorageSettings.ApplicationSettings;
if (token != null && store.Contains(token))
if (store.Remove(token) == true)
{
//Save it here :
store.save();
Debug.WriteLine("deleted after Remove " + token);
}
else
{
Debug.WriteLine("Not deleted after Remove " + token);
}
//Or call it here :
store.save();
}

How to get the document using view in couchbase

I have a requirement wherein I have get the document from couchbase.
Following in the Map function that I am using for the same -
function (doc, meta) {
if (meta.type == "json" && doc!=null) {
emit(doc);
}
}
There is no reduce function. Also following is my java code to get the document -
List<URI> hosts = Arrays.asList(
new URI("http://<some DNS with port>/pools")
);
// Name of the Bucket to connect to
String bucket = "Test-Sessions";
// Password of the bucket (empty) string if none
String password = "";
//System.setProperty("viewmode", "development");
// Connect to the Cluster
CouchbaseClient client = new CouchbaseClient(hosts, bucket, password);
String designDoc = "sessions";
String viewName = "by_test";
View view = client.getView(designDoc, viewName);
Query query = new Query();
query.setIncludeDocs(true);
query.setKey(String.valueOf(122));
ViewResponse result = client.query(view, query);
Object object = null;
for(ViewRow row : result) {
if(null != row) {
object = row.getDocument();
}// deal with the document/data
}
System.out.println("Object" + object);
And the data that I have in couchbase is key - "122" and value - "true". But for some reason , I do not get any rows in the ViewResponse. What is going wrong can anyone help?
I don't understand what you are trying to achieve here, you are using a view to get a document by it's key? Key == 122? Why can't you just do client.get(122) ?
If you just need a list of all the keys in your bucket (of which you can use to pull back all documents via include docs) then make your function like so:
function (doc, meta) {
if (meta.type == "json") {
emit();
}
}
The key of the document is always emitted as an ID (viewRow.getId()). You don't need to emit the document, try to emit as little data as possible to keep view sizes small.
If you are needing to manipulate all the documents in your bucket be careful as the size grows, perhaps you'd need to look at pagination to cycle through the results. http://tugdualgrall.blogspot.com.es/
Also once you have the ViewResponse loop over it like so:
for(ViewRow row : result) {
row.getDocument(); // deal with the document/data
}
You don't need to be doing checks for null on the rows.

Why does TRY / CATCH overwrite default property values?

I'm using a Value Object which can receive an object when it is instantiated, so its default values can be updated directly when a new VO is created, like so:
public class SeatSettingsVO
{
public var globalPosition:Point = new Point(0, 0);
public var dealerChipOffset:Point = new Point(0, 0);
public var chipStackOffset:Point = new Point(0, 0);
public function SeatSettingsVO(obj:Object = null)
{
if (obj)
parseSettings(obj);
}
}
The parseSettings method uses a try/catch block in order to get only the existing properties in the object passed to the constructor (or at least, that would be the intention):
private function parseSettings(obj:Object):void
{
try
{
this.globalPosition = obj.globalPosition;
this.chipStackOffset = obj.chipStackOffset;
this.dealerChipOffset = obj.dealerChipOffset;
}
catch (error:Error)
{
}
}
Now consider this scenario: a new Value Object needs to be created, but with only one of the three properties defined:
new SeatSettingsVO({globalPosition:new Point(300, 277)})
The problem is that if obj does not contain a particular property (e.g. chipStackOffset), instead of maintaining the initial property value (Point(0,0)), the method overwrites it to null.
My guess is that accessing non-existent properties on an Object class instance, does not trigger an error, but rather, null is returned, which in turn causes the default value to be overwritten. Can anyone explain this behavior, and possibly suggest a solution ?
Thank you very much.
A slightly more succinct solution than the others:
this.globalPosition = obj.globalPosition || DEFAULT_GLOBAL_POSITION;
Like in Python, the || operator returns the first operand if that operand evaluates to something besides 0, null, false, NaN, "", or undefined. Otherwise, it returns the second operand as-is:
trace(new Point(3, 3) || "hi"); //(x=3, y=3)
trace(false || "hi"); //hi
trace("hi" || "bye"); //hi
trace(0 || null); //null
trace(NaN || 0); //0
trace("" || undefined); //undefined
trace(undefined || new Point(0.4, 0)); //(x=0.4, y=0)
trace(null || false); //false
As a result, you can use it to check whether a value is defined, use that value if so, and use a default value if not. I'm honestly not sure if it makes your code more or less readable, but it's an option.
Flex Objects have a hasOwnProperty() method that you might find useful. You can use this to check if a dynamic object has a parameter defined, and only pull it if it exists, instead of getting nulls.
if (obj.hasOwnProperty("globalPosition"))
this.globalPosition = obj.globalPosition;
//etc...
In this case, your object is dynamic so you don't get an exception if the property doesn't exist. You do, however, get undefined. undefined evaluates to null, so you can always say:
this.globalPosition = obj.globalPosition ? obj.globalPosition : default;
where default is whatever you want to put there... even this.globalPosition would work if you want to set it back to what it was.
You can also ask if the property exists:
if( "globalPosition" in obj)
private function parseSettings(obj:Object):void
{
try
{
this.globalPosition = obj.globalPosition;
this.chipStackOffset = obj.chipStackOffset;// when error occured here,
// this.chipStackOffset still waiting for a value to set and it sets to null.
// probably dealerChipOffset doesnt change by default value.
this.dealerChipOffset = obj.dealerChipOffset; // this is {0,0} point prob,didnt try it.
}
catch (error:Error)
{
}
}
I would use somthing like below. Hope it helps.
private function parseSettings(obj:Object):void
{
for(var name in obj){
this[name] = obj[name];
}
}