Wednesday 15 August 2012

c# - Creating Edges with OrientDB-NET.binary in a transaction -



c# - Creating Edges with OrientDB-NET.binary in a transaction -

i trying utilize orientdb-net.binary, extending improve ease-of-use among development team. trying create syntax similar dapper, that's we're using our mssql , mysql connections. should create easier on our development team swapping between 2 technologies.

i'd extensions function transactions.

here's insert extension now:

class="lang-c# prettyprint-override">public static void insert<t>(this odatabase db, t model, otransaction transaction) t : abasemodel, new() { inserthelper(db, model, transaction, new list<object>()); } private static void inserthelper<t>(odatabase db, t model, otransaction transaction, icollection<object> exclude, orid parent = null) t : abasemodel, new() { // avoid next loops stack overflow if (exclude.contains(model)) return; exclude.add(model); odocument record = new odocument(); record.oclassname = model.gettype().name; propertyinfo[] properties = model.gettype().getproperties( bindingflags.public | bindingflags.instance | bindingflags.setproperty | bindingflags.getproperty); icollection<propertyinfo> linkableproperties = new list<propertyinfo>(); foreach (propertyinfo prop in properties) { if (reservedproperties.contains(prop.name)) continue; oproperty aliasproperty = prop.getcustomattributes(typeof(oproperty)) .where(attr => ((oproperty)attr).alias != null) .firstordefault() oproperty; string name = aliasproperty == null ? prop.name : aliasproperty.alias; // record properties of model, store properties linking other // vertex classes later if (typeof(abasemodel).isassignablefrom(prop.propertytype)) { linkableproperties.add(prop); } else { record[name] = prop.getvalue(model); } } transaction.add(record); model.orid = record.orid; foreach (propertyinfo prop in linkableproperties) { orid outv, inv; abasemodel propvalue = prop.getvalue(model) abasemodel; if (!exclude.select(ex => ex abasemodel ? ((abasemodel)ex).orid : orid_default).contains(propvalue.orid)) { methodinfo insertmethod = typeof(databaseextensions) .getmethod("inserthelper", bindingflags.nonpublic | bindingflags.static).makegenericmethod(propvalue.gettype()); insertmethod.invoke(null, new object[] { db, propvalue, transaction, exclude, model.orid }); } outv = model.orid; inv = propvalue.orid; oedgeattribute edgetype = prop.getcustomattributes(typeof(oedgeattribute)) .firstordefault() oedgeattribute; oproperty propertyalias = prop.getcustomattributes(typeof(oproperty)) .where(p => ((oproperty)p).alias != null) .firstordefault() oproperty; string alias = propertyalias == null ? prop.name : propertyalias.alias; if (edgetype != null) { oedge link = new oedge(); link.oclassname = alias; link["out"] = outv; link["in"] = inv; if(edgetype.isinv) { orid tmp = link.outv; link["out"] = link.inv; link["in"] = tmp; } // not create border if there border // connecting these vertices ienumerable<tuple<orid,orid>> excludedlinks = exclude .select(ex => ex oedge ? new tuple<orid,orid>(((oedge)ex).outv,((oedge)ex).inv) : new tuple<orid,orid>(orid_default, orid_default)); if (excludedlinks.contains( new tuple<orid, orid>(link.outv, link.inv))) continue; exclude.add(link); transaction.add(link); } } }

abasemodel abstract class intended extended model classes in application. oedgeattribute attribute lets me specify if property representing 'in' border or 'out' border on vertex. orid_default equal new orid()

the above extension method works fine... mostly. using next model classes:

class="lang-c# prettyprint-override">public class person : abasemodel { [oproperty(alias = "residenceaddress")] [oedge(isoutv = true)] public address residence { get; set; } [oproperty(alias = "shippingaddress")] [oedge(isoutv = true)] public address shipping { get; set; } } public class dependent : person { public string firstname { get; set; } public string lastname { get; set; } // etc... } public class address : abasemodel { public string addressline1 { get; set; } public string addressline2 { get; set; } // etc... [oproperty(alias = "propertyaddress")] public person resident { get; set; } }

i 'import' several hundred dependents mapping set of entries in table:

class="lang-c# prettyprint-override">oclient.createdatabasepool("127.0.0.1", 2424, "persephone", odatabasetype.graph, "admin", "admin", 10, "persephone"); // persephoneconnection has access odatabase , otransaction, // , methods dispatch them ipersephoneconnection persephone = new persephoneconnection(); persephone.begintransaction(); // traverse functioning extension method calls // `traverse * {0}` , maps result model objects ienumerable<tmped> eds = persephone.connection.traverse<tmped>("tmped"); foreach (tmped model in eds) { dependent dep = new dependent { firstname = model.firstname, lastname = model.lastname, // etc... }; address residence = new address { addressline1 = model.addres_line1, addressline2 = model.address_line2, // etc... resident = dep }; dep.residence = residence; address shipping = new address { addressline1 = model.shippingaddress_line1, addressline2 = model.shippingaddres_line2, // etc... resident = dep }; dep.shipping = shipping; persephone.connection.insert(dep, persephone.transaction); } persephone.commit(); persephone.dispose();

after running code, database contains 273 dependent records (extends person extends v) right values properties, 546 address records (extends v) right values properties, 273 residenceaddress records (extends propertyaddress extends e) right out , in rids, , 273 shippingaddress records (extends propertyaddress) right out , in rids.

however, none of dependents or addresses can see edges connect them. traverse * #29:0 brings first dependent, doesn't bring residence or shipping address. select expand(out('residenceaddress')) dependent returns empty result set.

after tinkering, appears cause of because otransaction.add performing insert {0} when transaction committed, rather create vertex {0} or create border {0}.

i can alter code utilize odatabase.create.vertex() , odatabase.create.edge() instead of otransaction.add(), instead of committing transaction in case, have phone call osqlcreateedge.run() or osqlcreatevertex.run(), processes record creation immediately, , rollback isn't option.

is there way edges created (as opposed inserted records) while still using transactions?

to create heavy edges via transaction need proper set links between documents

look illustration here

var v1 = new odocument { oclassname = "testvertex" }; v1.setfield("name", "first"); v1.setfield("bar", 1); var v2 = new odocument { oclassname = "testvertex" }; v2.setfield("name", "second"); v2.setfield("bar", 2); var e1 = new odocument { oclassname = "testedge" }; e1.setfield("weight", 1.3f); // add together records transaction _database.transaction.add(v1); _database.transaction.add(v2); _database.transaction.add(e1); // link records v1.setfield("in_testedge", e1.orid); v2.setfield("out_testedge", e1.orid); e1.setfield("in", v1.orid); e1.setfield("out", v2.orid); _database.transaction.commit();

c# orientdb

No comments:

Post a Comment