web services - How do I update with a newly-created detached entity using NHibernate? -
explanation:
let's have object graph that's nested several levels deep , each entity has bi-directional relationship each other.
a -> b -> c -> d -> e
or in other words, a
has collection of b
, b
has reference a
, , b
has collection of c
, c
has reference b
, etc...
now let's want edit data instance ofc
. in winforms, use this:
var instanceofc; using (var session = sessionfactory.opensession()) { // instance of c id = 3 instanceofc = session.linq<c>().where(x => x.id == 3); } sendtouiandletuserupdatedata(instanceofc); using (var session = sessionfactory.opensession()) { // re-attach detached entity , update session.update(instanceofc); }
in plain english, grab persistent instance out of database, detach it, give ui layer editing, re-attach , save database.
problem:
this works fine winform applications because we're using same entity throughout, difference being goes persistent detached persistent again.
the problem i'm using web service , browser, sending on json data. entity gets serialized string, , de-serialized new entity. it's no longer detached entity, rather transient 1 happens have same id persistent 1 (and updated fields). if use entity update, wipe out relationship b
, d
because don't exist in new transient entity.
question:
my question is, how serialize detached entities on web client, receive them back, , save them, while preserving relationships didn't explicitly change? know isession.saveorupdatecopy
, isession.merge()
(they seem same thing?), still wipe out relationships if don't explicitly set them. copy fields transient entity persistent entity 1 one, doesn't work when comes relationships , i'd have handle version comparisons manually.
i solved problem using intermediate class hold data coming in web service, copying properties database entity. example, let's have 2 entities so:
entity classes
public class album { public virtual int id { get; set; } public virtual icollection photos { get; set; } } public class photo { public virtual int id { get; set; } public virtual album album { get; set; } public virtual string name { get; set; } public virtual string pathtofile { get; set; } }
album
contains collection of photo
objects, , photo
has reference album
it's in, it's bidirectional relationship. create photodto
class:
dto class
public class photodto { public virtual int id { get; set; } public virtual int albumid { get; set; } public virtual string name { get; set; } // note dto not have pathtofile property }
now let's have following photo
stored in database:
server data
new photo { id = 15, name = "fluffy kittens", album = session.load<album>(3) };
the client wants update photo's name. send on following json server:
client data
{ "id": 15, "albumid": 3, "name": "angry kittens" }
the server deserializes json photodto
object. on server side, update photo
this:
server code
var photodto = deserializejson(); var photodb = session.load(photodto.id); // or use id in url // copy properties photodto photodb photodb.name = photodto.name; photodb.album = session.load<album>(photodto.albumid); session.flush(); // save changes db
explanation
this best solution i've found because:
you can choose properties client allowed modify. example,
photodto
doesn't havepathtofile
property, client can never modify it.you can choose whether update property or not. example, if client didn't send on
albumid
, 0. can check , not changealbum
if id 0. likewise, if user doesn't send onname
, can choose not update property.you don't have worry lifecycle of entity because retrieved , updated within scope of single session.
automapper
i recommend using automapper automatically copy properties dto entity, if entites have lot of properties. saves trouble of having write every property hand, , has lot of configurability.
Comments
Post a Comment