Skip to content

Commit 0644587

Browse files
committed
NH-3372: Enabled use of generated properties in combination with custom loader.
1 parent 89fd30a commit 0644587

File tree

4 files changed

+163
-147
lines changed

4 files changed

+163
-147
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace NHibernate.Test.NHSpecificTest.NH3372
2+
{
3+
public class Entity
4+
{
5+
public int Id { get; set; }
6+
public string ShardId { get; set; }
7+
public string Content { get; set; }
8+
}
9+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using NUnit.Framework;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH3372
4+
{
5+
[TestFixture]
6+
public class Fixture : BugTestCase
7+
{
8+
protected override bool AppliesTo(Dialect.Dialect dialect)
9+
{
10+
return dialect is NHibernate.Dialect.MsSql2000Dialect;
11+
}
12+
13+
[Test]
14+
public void CanGeneratePropertyOnInsertOfEntityWithCustomLoader()
15+
{
16+
using (var session = OpenSession())
17+
using (session.BeginTransaction())
18+
{
19+
var entity = new Entity { Content = "Some text" };
20+
session.Save(entity);
21+
session.Flush();
22+
23+
Assert.That(entity.ShardId, Is.Not.Null & Has.Length.GreaterThan(0));
24+
}
25+
}
26+
27+
[Test]
28+
public void CanGeneratePropertyOnUpdateOfEntityWithCustomLoader()
29+
{
30+
using (var session = OpenSession())
31+
using (session.BeginTransaction())
32+
{
33+
var entity = new Entity { Content = "Some text" };
34+
session.Save(entity);
35+
session.Flush();
36+
37+
entity.ShardId = null;
38+
entity.Content = "Some other text";
39+
session.Update(entity);
40+
session.Flush();
41+
42+
Assert.That(entity.ShardId, Is.Not.Null & Has.Length.GreaterThan(0));
43+
}
44+
}
45+
46+
}
47+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
assembly="NHibernate.Test"
4+
namespace="NHibernate.Test.NHSpecificTest.NH3372">
5+
6+
<class name="Entity" table="entity" lazy="false">
7+
<id name="Id" column="id" generator="native" />
8+
<property name="ShardId" generated="always" insert="false" update="false" />
9+
<property name="Content" column="content" />
10+
<loader query-ref="LoadEntity" />
11+
</class>
12+
13+
<sql-query name="LoadEntity" xml:space="preserve">
14+
<return class="Entity" alias="e" />
15+
SELECT id AS {e.Id}
16+
, DB_NAME() AS {e.ShardId}
17+
, content AS {e.Content}
18+
FROM entity
19+
WHERE id = ?
20+
</sql-query>
21+
</hibernate-mapping>

src/NHibernate/Persister/Entity/AbstractEntityPersister.cs

Lines changed: 86 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,14 +1271,14 @@ private object InitializeLazyPropertiesFromDatastore(string fieldName, object en
12711271
catch (DbException sqle)
12721272
{
12731273
var exceptionContext = new AdoExceptionContextInfo
1274-
{
1275-
SqlException = sqle,
1276-
Message =
1277-
"could not initialize lazy properties: " + MessageHelper.InfoString(this, id, Factory),
1278-
Sql = SQLLazySelectString.ToString(),
1279-
EntityName = EntityName,
1280-
EntityId = id
1281-
};
1274+
{
1275+
SqlException = sqle,
1276+
Message =
1277+
"could not initialize lazy properties: " + MessageHelper.InfoString(this, id, Factory),
1278+
Sql = SQLLazySelectString.ToString(),
1279+
EntityName = EntityName,
1280+
EntityId = id
1281+
};
12821282
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
12831283
}
12841284
}
@@ -1444,13 +1444,13 @@ public object[] GetDatabaseSnapshot(object id, ISessionImplementor session)
14441444
catch (DbException sqle)
14451445
{
14461446
var exceptionContext = new AdoExceptionContextInfo
1447-
{
1448-
SqlException = sqle,
1449-
Message = "could not retrieve snapshot: " + MessageHelper.InfoString(this, id, Factory),
1450-
Sql = SQLSnapshotSelectString.ToString(),
1451-
EntityName = EntityName,
1452-
EntityId = id
1453-
};
1447+
{
1448+
SqlException = sqle,
1449+
Message = "could not retrieve snapshot: " + MessageHelper.InfoString(this, id, Factory),
1450+
Sql = SQLSnapshotSelectString.ToString(),
1451+
EntityName = EntityName,
1452+
EntityId = id
1453+
};
14541454
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
14551455
}
14561456
}
@@ -1627,13 +1627,13 @@ public object ForceVersionIncrement(object id, object currentVersion, ISessionIm
16271627
catch (DbException sqle)
16281628
{
16291629
var exceptionContext = new AdoExceptionContextInfo
1630-
{
1631-
SqlException = sqle,
1632-
Message = "could not retrieve version: " + MessageHelper.InfoString(this, id, Factory),
1633-
Sql = VersionSelectString.ToString(),
1634-
EntityName = EntityName,
1635-
EntityId = id
1636-
};
1630+
{
1631+
SqlException = sqle,
1632+
Message = "could not retrieve version: " + MessageHelper.InfoString(this, id, Factory),
1633+
Sql = VersionSelectString.ToString(),
1634+
EntityName = EntityName,
1635+
EntityId = id
1636+
};
16371637
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
16381638
}
16391639
return nextVersion;
@@ -1689,13 +1689,13 @@ public object GetCurrentVersion(object id, ISessionImplementor session)
16891689
catch (DbException sqle)
16901690
{
16911691
var exceptionContext = new AdoExceptionContextInfo
1692-
{
1693-
SqlException = sqle,
1694-
Message = "could not retrieve version: " + MessageHelper.InfoString(this, id, Factory),
1695-
Sql = VersionSelectString.ToString(),
1696-
EntityName = EntityName,
1697-
EntityId = id
1698-
};
1692+
{
1693+
SqlException = sqle,
1694+
Message = "could not retrieve version: " + MessageHelper.InfoString(this, id, Factory),
1695+
Sql = VersionSelectString.ToString(),
1696+
EntityName = EntityName,
1697+
EntityId = id
1698+
};
16991699
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
17001700
}
17011701
}
@@ -2137,7 +2137,7 @@ private void InitIdentifierPropertyPaths(IMapping mapping)
21372137
private void InitDiscriminatorPropertyPath()
21382138
{
21392139
propertyMapping.InitPropertyPaths(EntityClass, DiscriminatorType, new string[] {DiscriminatorColumnName},
2140-
new string[] {DiscriminatorFormulaTemplate}, Factory);
2140+
new string[] {DiscriminatorFormulaTemplate}, Factory);
21412141
}
21422142

21432143
private void InitPropertyPaths(IMapping mapping)
@@ -2664,13 +2664,13 @@ protected void Insert(object id, object[] fields, bool[] notNull, int j,
26642664
catch (DbException sqle)
26652665
{
26662666
var exceptionContext = new AdoExceptionContextInfo
2667-
{
2668-
SqlException = sqle,
2669-
Message = "could not insert: " + MessageHelper.InfoString(this, id),
2670-
Sql = sql.ToString(),
2671-
EntityName = EntityName,
2672-
EntityId = id
2673-
};
2667+
{
2668+
SqlException = sqle,
2669+
Message = "could not insert: " + MessageHelper.InfoString(this, id),
2670+
Sql = sql.ToString(),
2671+
EntityName = EntityName,
2672+
EntityId = id
2673+
};
26742674
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
26752675
}
26762676
}
@@ -2807,13 +2807,13 @@ protected bool Update(object id, object[] fields, object[] oldFields, object row
28072807
catch (DbException sqle)
28082808
{
28092809
var exceptionContext = new AdoExceptionContextInfo
2810-
{
2811-
SqlException = sqle,
2812-
Message = "could not update: " + MessageHelper.InfoString(this, id, Factory),
2813-
Sql = sql.Text.ToString(),
2810+
{
2811+
SqlException = sqle,
2812+
Message = "could not update: " + MessageHelper.InfoString(this, id, Factory),
2813+
Sql = sql.Text.ToString(),
28142814
EntityName = EntityName,
28152815
EntityId = id
2816-
};
2816+
};
28172817
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
28182818
}
28192819
}
@@ -2927,13 +2927,13 @@ public void Delete(object id, object version, int j, object obj, SqlCommandInfo
29272927
catch (DbException sqle)
29282928
{
29292929
var exceptionContext = new AdoExceptionContextInfo
2930-
{
2931-
SqlException = sqle,
2932-
Message = "could not delete: " + MessageHelper.InfoString(this, id, Factory),
2933-
Sql = sql.Text.ToString(),
2934-
EntityName = EntityName,
2935-
EntityId = id
2936-
};
2930+
{
2931+
SqlException = sqle,
2932+
Message = "could not delete: " + MessageHelper.InfoString(this, id, Factory),
2933+
Sql = sql.Text.ToString(),
2934+
EntityName = EntityName,
2935+
EntityId = id
2936+
};
29372937
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
29382938
}
29392939
}
@@ -3199,73 +3199,11 @@ protected void LogStaticSQL()
31993199
public virtual string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters)
32003200
{
32013201
StringBuilder sessionFilterFragment = new StringBuilder();
3202-
3203-
filterHelper.Render(sessionFilterFragment, GenerateFilterConditionAlias(alias), GetColumnsToTableAliasMap(alias), enabledFilters);
3202+
filterHelper.Render(sessionFilterFragment, GenerateFilterConditionAlias(alias), enabledFilters);
32043203

32053204
return sessionFilterFragment.Append(FilterFragment(alias)).ToString();
32063205
}
32073206

3208-
private IDictionary<string, string> GetColumnsToTableAliasMap(string rootAlias)
3209-
{
3210-
IDictionary<PropertyKey, string> propDictionary = new Dictionary<PropertyKey, string>();
3211-
for (int i =0; i < SubclassPropertyNameClosure.Length; i++)
3212-
{
3213-
string property = SubclassPropertyNameClosure[i];
3214-
string[] cols = GetSubclassPropertyColumnNames(property);
3215-
3216-
if (cols != null && cols.Length > 0)
3217-
{
3218-
PropertyKey key = new PropertyKey(cols[0], GetSubclassPropertyTableNumber(i));
3219-
propDictionary[key] = property;
3220-
}
3221-
}
3222-
3223-
IDictionary<string, string> dict = new Dictionary<string, string>();
3224-
for (int i = 0; i < SubclassColumnTableNumberClosure.Length; i++ )
3225-
{
3226-
string col = SubclassColumnClosure[i];
3227-
string alias = GenerateTableAlias(rootAlias, SubclassColumnTableNumberClosure[i]);
3228-
3229-
string fullColumn = string.Format("{0}.{1}", alias, col);
3230-
3231-
PropertyKey key = new PropertyKey(col, SubclassColumnTableNumberClosure[i]);
3232-
if (propDictionary.ContainsKey(key))
3233-
{
3234-
dict[propDictionary[key]] = fullColumn;
3235-
}
3236-
3237-
if (!dict.ContainsKey(col))
3238-
{
3239-
dict[col] = fullColumn;
3240-
}
3241-
}
3242-
3243-
return dict;
3244-
}
3245-
3246-
private class PropertyKey
3247-
{
3248-
public string Column { get; set; }
3249-
public int TableNumber { get; set; }
3250-
3251-
public PropertyKey(string column, int tableNumber)
3252-
{
3253-
Column = column;
3254-
TableNumber = tableNumber;
3255-
}
3256-
3257-
public override int GetHashCode()
3258-
{
3259-
return Column.GetHashCode() ^ TableNumber.GetHashCode();
3260-
}
3261-
3262-
public override bool Equals(object other)
3263-
{
3264-
PropertyKey otherTuple = other as PropertyKey;
3265-
return otherTuple == null ? false : Column.Equals(otherTuple.Column) && TableNumber.Equals(otherTuple.TableNumber);
3266-
}
3267-
}
3268-
32693207
public virtual string GenerateFilterConditionAlias(string rootAlias)
32703208
{
32713209
return rootAlias;
@@ -3746,34 +3684,35 @@ public virtual void AfterReassociate(object entity, ISessionImplementor session)
37463684
return true;
37473685
}
37483686

3749-
// check the id unsaved-value
3750-
// We do this first so we don't have to hydrate the version property if the id property already gives us the info we need (NH-3505).
3751-
bool? result2 = entityMetamodel.IdentifierProperty.UnsavedValue.IsUnsaved(id);
3752-
if (result2.HasValue)
3753-
{
3754-
if (IdentifierGenerator is Assigned)
3755-
{
3756-
// if using assigned identifier, we can only make assumptions
3757-
// if the value is a known unsaved-value
3758-
if (result2.Value)
3759-
return true;
3760-
}
3761-
else
3762-
{
3763-
return result2;
3764-
}
3765-
}
3766-
3767-
// check the version unsaved-value, if appropriate
3768-
if (IsVersioned)
3769-
{
3770-
object version = GetVersion(entity, session.EntityMode);
3771-
bool? result = entityMetamodel.VersionProperty.UnsavedValue.IsUnsaved(version);
3772-
if (result.HasValue)
3773-
{
3774-
return result;
3775-
}
3776-
}
3687+
// check the version unsaved-value, if appropriate
3688+
if (IsVersioned)
3689+
{
3690+
object version = GetVersion(entity, session.EntityMode);
3691+
// let this take precedence if defined, since it works for
3692+
// assigned identifiers
3693+
bool? result = entityMetamodel.VersionProperty.UnsavedValue.IsUnsaved(version);
3694+
if (result.HasValue)
3695+
{
3696+
return result;
3697+
}
3698+
}
3699+
3700+
// check the id unsaved-value
3701+
bool? result2 = entityMetamodel.IdentifierProperty.UnsavedValue.IsUnsaved(id);
3702+
if (result2.HasValue)
3703+
{
3704+
if (IdentifierGenerator is Assigned)
3705+
{
3706+
// if using assigned identifier, we can only make assumptions
3707+
// if the value is a known unsaved-value
3708+
if (result2.Value)
3709+
return true;
3710+
}
3711+
else
3712+
{
3713+
return result2;
3714+
}
3715+
}
37773716

37783717
// check to see if it is in the second-level cache
37793718
if (HasCache)
@@ -4167,13 +4106,13 @@ public virtual object[] GetNaturalIdentifierSnapshot(object id, ISessionImplemen
41674106
catch (DbException sqle)
41684107
{
41694108
var exceptionContext = new AdoExceptionContextInfo
4170-
{
4171-
SqlException = sqle,
4172-
Message = "could not retrieve snapshot: " + MessageHelper.InfoString(this, id, Factory),
4173-
Sql = sql.ToString(),
4174-
EntityName = EntityName,
4175-
EntityId = id
4176-
};
4109+
{
4110+
SqlException = sqle,
4111+
Message = "could not retrieve snapshot: " + MessageHelper.InfoString(this, id, Factory),
4112+
Sql = sql.ToString(),
4113+
EntityName = EntityName,
4114+
EntityId = id
4115+
};
41774116
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, exceptionContext);
41784117
}
41794118
}

0 commit comments

Comments
 (0)