Hey again,
Still testing the features of disconnected state, found myself again in trouble. As usual, here's the scenario.
(1) Simple set of entities:
[HierarchyRoot]
public class Entity1 : Entity
{
[Field, Key]
public Int32 Id { get; private set; }
[Field]
public String Name { get; set; }
[Field]
[Association("One")]
public EntitySet<Entity2> Two { get; set; }
}
[HierarchyRoot]
public class Entity2 : Entity
{
[Field, Key]
public Int32 Id { get; private set; }
[Field]
public String Name { get; set; }
[Field]
public EntitySet<Entity1> One { get; set; }
[Field]
public EntitySet<Entity3> Three { get; set; }
}
[HierarchyRoot]
public class Entity3 : Entity
{
[Field, Key]
public Int32 Id { get; private set; }
[Field]
public String Name { get; set; }
[Field]
[Association("Three")]
public EntitySet<Entity2> Two { get; set; }
}
}
(2) Simple console application, manipulating everything on main body:
static void Main(string[] args)
{
//DB was previously populated, code supplied below.
DomainConfiguration config2 = new DomainConfiguration("sqlserver",
"Data Source=localhost\\SQLEXPRESS; Initial Catalog=NewTemp; " +
"Integrated Security=True; MultipleActiveResultSets=true;")
{
UpgradeMode = DomainUpgradeMode.Validate
};
config2.Types.Register(typeof(Domain.Entity1).Assembly, typeof(Domain.Entity1).Namespace);
//Create Domain/Session, with ServerProfile option.
Xtensive.Orm.Domain firstDomain = Xtensive.Orm.Domain.Build(config2);
Xtensive.Orm.Configuration.SessionConfiguration configSession = new SessionConfiguration("mySession", SessionOptions.ServerProfile);
Xtensive.Orm.Session aSession = firstDomain.OpenSession(configSession);
//Create and Attach Disconnected State to the session.
Xtensive.Orm.DisconnectedState aState = new Xtensive.Orm.DisconnectedState();
aState.Attach(aSession);
aSession.Activate();
Xtensive.Orm.TransactionScope aTransaction = aSession.OpenTransaction();
Domain.Entity1 anEntity1;
//<IMPORTANT POINT 1> Run a simple query on Entity1 (it has a Many-to-Many with Entity2 which in turn has a Many-to-Many with Entity3).
anEntity1 = aSession.Query.All<Domain.Entity1>().Single(e1 => e1.Name == "One-1");
//<IMPORTANT POINT 2> Attempt to read anEntity1.Entity2[0].Entity3[0].Name (i.e. 2 levels deep in the entity graph)
String name = anEntity1.Two.ToList()[0].Three.ToList()[0].Name;
//<IMPORTANT POINT 3> Attempt to change the value read above
anEntity1.Two.ToList()[0].Three.ToList()[0].Name = "Changed-Name";
aTransaction.Complete();
aTransaction.Dispose();
//<IMPORTANT POINT 4> Save the disconnected state changes to persist the change
aState.ApplyChanges();
aSession.Dispose();
}
Considering the above, my doubts:
(1) In <important point="" 1=""> I didn't expect to be able to query for Entity1, since this Entity1 is not in cache (application just started, it's the main body) and I'm in disconnected state withou issuing a .Connect() command. Still, the query succeeds.
(2) In <important point="" 2=""> I was expecting that, even if the query above worked (as it did) this particular operation would fail. From the documentation I understood that EntitySets were always lazy-loaded (and this is non-overridable except by an explicit call to ".Prefetch()" on the query which isn't there) and that the EntitySets were only going to be populated on enumeration. So, in disconnected state, without .Connect() I didn't expect neither anEntity1.Two.ToList()[0] nor .Three.ToList()[0] to provide me any valid entities for the same reasons of the first question (they shouldn't be in cache, it's a disconnected state without .Connect and they're both being enumerated just then).
(3) <important point="" 4=""> is basically just a validation. I can be pretty sure that disconnected state is correctly initialized since the change made in <important point="" 3=""> won't be persisted in database if .ApplyChanges() is commented out, but they'll be persisted correctly with this line present. So, I believe the general setup is ok.
What's happenning? What am I missing?
Regards,
Pedro
P.S.: As extra info, here's the code that made the initial population of the DB:
private void populate()
{
DomainConfiguration config = new DomainConfiguration("sqlserver",
"Data Source=localhost\\SQLEXPRESS; Initial Catalog=NewTemp; " +
"Integrated Security=True; MultipleActiveResultSets=true;")
{
UpgradeMode = DomainUpgradeMode.Recreate
};
config.Types.Register(typeof(Domain.Entity1).Assembly, typeof(Domain.Entity1).Namespace);
using (var firstDomain = Xtensive.Orm.Domain.Build(config))
{
using (var aSession = firstDomain.OpenSession())
{
aSession.Activate();
using (var aTransaction = aSession.OpenTransaction())
{
for (int i = 0; i < 1000; i++)
{
Domain.Entity3 anEntity3 = new Domain.Entity3();
anEntity3.Name = "Three-" + i.ToString();
}
for (int i = 0; i < 100; i++)
{
Domain.Entity2 anEntity2 = new Domain.Entity2();
anEntity2.Name = "Two-" + i.ToString();
anEntity2.Three.AddRange(aSession.Query.All<Domain.Entity3>().Where(e3 => e3.Name.Contains(i.ToString())));
}
for (int i = 0; i < 10; i++)
{
Domain.Entity1 anEntity1 = new Domain.Entity1();
anEntity1.Name = "One-" + i.ToString();
anEntity1.Two.AddRange(aSession.Query.All<Domain.Entity2>().Where(e2 => e2.Name.Contains(i.ToString())));
}
aTransaction.Complete();
}
}
}
}
asked
Jun 15 '12 at 14:28
pgoes
21●6●6●10