我有一个包含Song对象的数据库。歌曲类有> 30个房产。
我的音乐标记应用程序正在对文件系统上的歌曲进行更改。 然后使用文件名在数据库中进行查找。
现在我有一个Song对象,我在我的Tagging应用程序中通过读取物理文件创建了一个Song对象,我刚刚从数据库中检索到了我要更新的对象。 我以为我可以从数据库对象中获取ID,用我的本地歌曲对象替换数据库对象,设置保存的ID并存储它。 但是Raven声称我用不同的对象替换了对象。
我是否真的需要复制每一个属性,就像这样?
dbSong.Artist = songfromFilesystem.Artist;
dbSong.Album = songfromFileSystem.Album;
还是有其他可能性。
感谢,
赫尔穆特
编辑:
我有点太积极了。以下建议仅适用于测试程序。 在我的原始代码中执行此操作时,我得到以下异常:
Attempted to associate a different object with id 'TrackDatas/3452'
这是由以下代码生成的:
try
{
originalFileName = Util.EscapeDatabaseQuery(originalFileName);
// Lookup the track in the database
var dbTracks = _session.Advanced.DocumentQuery<TrackData, DefaultSearchIndex>().WhereEquals("Query", originalFileName).ToList();
if (dbTracks.Count > 0)
{
track.Id = dbTracks[0].Id;
_session.Store(track);
_session.SaveChanges();
}
}
catch (Exception ex)
{
log.Error("UpdateTrack: Error updating track in database {0}: {1}", ex.Message, ex.InnerException);
}
我首先在数据库中查找一首歌并在dbTracks中获取一个TrackData对象。
track对象也是TrackData类型,我只是从刚刚检索到的对象中放入ID并尝试存储它,这就产生了上述错误。
我认为上面的消息告诉我对象属于不同的类型,而不是。
如果我使用AutoMapper,则会发生同样的错误。
任何想法?
答案 0 :(得分:1)
您可以执行您尝试的操作:仅使用ID替换现有对象。如果它不起作用,你可能会做错其他的事情。 (在这种情况下,请告诉我们您的代码。)
在Raven中更新现有对象时,有几个选项:
选项1:只需使用与现有对象相同的ID保存对象:
var song = ... // load it from the file system or whatever
song.Id = "Songs/5"; // Set it to an existing song ID
DbSession.Store(song); // Overwrites the existing song
选项2:手动更新现有对象的属性。
var song = ...;
var existingSong = DbSession.Load<Song>("Songs/5");
existingSong.Artist = song.Artist;
existingSong.Album = song.Album;
选项3:动态更新现有对象:
var song = ...;
var existingSong = DbSession.Load<Song>("Songs/5");
existingSong.CopyFrom(song);
你有这样的代码:
// Inside Song.cs
public virtual void CopyFrom(Song other)
{
var props = typeof(Song)
.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
.Where(p => p.CanWrite);
foreach (var prop in props)
{
var source = prop.GetValue(other);
prop.SetValue(this, source);
}
}
如果您经常发现自己必须这样做,请使用像AutoMapper这样的库。
Automapper可以使用一行代码自动将一个对象复制到另一个对象。
答案 1 :(得分:0)
现在您已经发布了一些代码,我看到了两件事:
首先,您是否有使用Advanced.DocumentQuery语法的原因?
// This is advanced query syntax. Is there a reason you're using it?
var dbTracks = _session.Advanced.DocumentQuery<TrackData, DefaultSearchIndex>().WhereEquals("Query", originalFileName).ToList();
以下是我如何使用标准LINQ语法编写代码:
var escapedFileName = Util.EscapeDatabaseQuery(originalFileName);
// Find the ID of the existing track in the database.
var existingTrackId = _session.Query<TrackData, DefaultSearchIndex>()
.Where(t => t.Query == escapedFileName)
.Select(t => t.Id);
if (existingTrackId != null)
{
track.Id = existingTrackId;
_session.Store(track);
_session.SaveChanges();
}
最后,#2:什么是赛道?它是通过session.Load还是session.Query加载的?如果是这样,那将无法正常工作,并且会导致您的问题。如果从数据库加载了跟踪,则您需要创建一个新对象并保存:
var escapedFileName = Util.EscapeDatabaseQuery(originalFileName);
// Find the ID of the existing track in the database.
var existingTrackId = _session.Query<TrackData, DefaultSearchIndex>()
.Where(t => t.Query == escapedFileName)
.Select(t => t.Id);
if (existingTrackId != null)
{
var newTrack = new Track(...);
newTrack.Id = existingTrackId;
_session.Store(newTrack);
_session.SaveChanges();
}
答案 2 :(得分:0)
这意味着您在会话中已经有一个具有相同ID的不同对象。对我来说,解决方法是使用一个新的会话。