私が取り組んでいるプロジェクトでは、システム内のデータと別のシステムのデータを同期させる必要があります。ものすごく大事)。しかし、複合IDを持つ既存のエンティティを更新しようとすると、私は奇妙な問題を抱えています。エンティティが以前に取得されたエンティティをコンポジットIDでマージできない場合Get
問題が更新されるエンティティが取得されるたびに(変更はDBに永続化されませんが、例外がスローされない)前に、それは動作しませんマージを呼び出す(を取得を使用して)ということです。 へのコールを削除すると、が取得され、エンティティの更新が機能します。エンティティが存在するかどうかの知識が必要です。なぜなら、エンティティが作成されていると、複合IDの一部を生成する必要があるからです。
bool exists = ScanForInstance(instance);
using (var session = SessionFactoryFactory.GetSessionFactory<T>().OpenSession())
{
if (exists)
{
instance = (T)session.Merge(instance);
}
else
{
KeyGenerator.Assign<T>(instance);
newId = session.Save(instance);
}
session.Flush();
}
取得コールがScanForInstance方法で行われる:
private bool ScanForInstance<T>(T instance)
where T : class
{
var id = IdResolver.ResolveObject<T>(instance);
using (var session = SessionFactoryFactory.GetSessionFactory<T>().OpenStatelessSession())
{
return session.Get<T>(id) != null;
}
}
IdResolver
をID(単一のキーの値を使用すべきか決定するために使用されますマッピングでは、複合IDを持つエンティティのオブジェクトそのもの)。私が言ったように、への呼び出しを取り除くと、がうまく動作します。他のすべての操作(作成、読み取り、および削除)でも正常に動作します。更新を含むすべての操作は、単一のキーを持つエンティティで正常に機能します。
DBは広汎であり、制限の一定数存在する。
- いいえ、私は(私はFNBの問題を頻繁に応答としてそれを参照)スキーマを変更することはできません。私がしました:私は、我々は戻って私たちのシステムに同期していないと私が更新
をこれらを一掃したくない一部の列があるとして挿入し、削除したくない
マッピングするタイプ、流暢マッピング: 'ParentType'
public class ParentType
{
public virtual long AssignedId { get; set; }
public virtual long? GeneratedId { get; set; }
public virtual string SomeField { get; set; }
public override bool Equals(object obj)
{
return Equals(obj as ParentType);
}
private bool Equals(ParentType other)
{
if (ReferenceEquals(this, other)) return true;
if (ReferenceEquals(null, other)) return false;
return AssignedId == other.AssignedId &&
GeneratedId == other.GeneratedId;
}
public override int GetHashCode()
{
unchecked
{
int hash = GetType().GetHashCode();
hash = (hash * 31)^AssignedId.GetHashCode();
hash = (hash * 31)^GeneratedId.GetHashCode();
return hash;
}
}
}
public class ParentMap : ClassMap<ParentType>
{
public ParentMap()
{
Table("STANDARDTASKITEM");
CompositeId()
.KeyProperty(x => x.AssignedId, "STANDARDTASK")
.KeyProperty(x => x.GeneratedId, "STANDARDTASKITEM");
Map(x => x.SomeField, "DESCRIPTION");
Not.LazyLoad();
}
}
、それが呼び出された事実を気にしないでください。私は実際にこれと他のマッピングを持っていないし、この例では親の型として型を実際に使用しません。私はコンポジットIDと継承に関する問題(複合IDを使用しないでください:-D)を含む別の質問を開こうとしているので、これはこれと呼ばれています。
実際のテストのために、私はちょうどプログラムとしてVSでコンソールプロジェクトを作成しました。CS:
static void Main(string[] args)
{
var smFactory = Fluently.Configure()
.Database(() => new OdbcPersistenceConfigurer()
.Driver<OdbcDriver>()
.Dialect<GenericDialect>()
.Provider<DriverConnectionProvider>()
.ConnectionString(BuildSMConnectionString())
.ProxyFactoryFactory(typeof(NHibernate.ByteCode.Castle.ProxyFactoryFactory))
.UseReflectionOptimizer()
.UseOuterJoin())
.Mappings
(m =>
m.FluentMappings.Add<ParentMap>()
);
var sessionFactory = smFactory.BuildSessionFactory();
var updatedInstance = new ParentType
{
AssignedId = 1,
GeneratedId = 13,
SomeField = "UPDATED"
};
bool exists;
using (var session = sessionFactory.OpenStatelessSession())
{
exists = session.Get<ParentType>(updatedInstance) != null;
}
using (var session = sessionFactory.OpenSession())
{
if (exists)
{
session.Merge(updatedInstance);
session.Flush();
}
}
}
private static string BuildSMConnectionString()
{
// Return your connection string here
}
class OdbcPersistenceConfigurer : PersistenceConfiguration<OdbcPersistenceConfigurer, OdbcConnectionStringBuilder>
{
}
私はこれをテストしたい人は、彼らはすでに自分のDBを持っていることを表に準拠するようにParentTypeフィールドを変更する必要がありますいずれかのため、このサンプルの追加はわずかにより有用であることを知っている、またはParentTypeにマップされているものと一致するテーブルを追加します。私はテストで良いスタートを切ったので、誰かが好奇心から少なくともこれをやることを望んでいます。
は、あなたはそれが例外をスローしたり、何もしません意味ですか? – eulerfx
@eulerfx申し訳ありませんが、問題は例外がスローされていない間に変更がDBに残っていないことでした。私はこれを反映するために質問を更新し、人々がこの動作をテストしたい場合に備えていくつかのサンプルコードを追加しました。 – docmanhattan