我有一个包含 Song 对象的数据库.歌曲类有 > 30 个属性.
i have a database containing Song objects. The song class has > 30 properties.
我的音乐标记应用程序正在对文件系统上的歌曲进行更改.然后它使用文件名在数据库中进行查找.
My Music Tagging application is doing changes on a song on the file system. It then does a lookup in the database using the filename.
现在我有一个 Song 对象,它是我通过读取物理文件在我的 Tagging 应用程序中创建的,我有一个 Song 对象,我刚刚从数据库中检索了它并且我想更新它.我以为我可以从数据库对象中获取 ID,用我的本地歌曲对象替换数据库对象,设置保存的 ID 并存储它.但是 Raven 声称我正在用不同的对象替换该对象.
Now i have a Song object, which i created in my Tagging application by reading the physical file and i have a Song object, which i have just retrieved from the database and which i want to update. I thought i just could grab the ID from the database object, replace the database object with my local song object, set the saved id and store it. But Raven claims that i am replacing the object with a different object.
我真的需要像这样复制每个属性吗?
Do i really need to copy every single property over, like this?
dbSong.Artist = songfromFilesystem.Artist;
dbSong.Artist = songfromFilesystem.Artist;
dbSong.Album = songfromFileSystem.Album;
dbSong.Album = songfromFileSystem.Album;
或者还有其他可能性.
谢谢,
赫尔穆特
我有点过于积极了.以下建议仅适用于测试程序.在我的原始代码中执行此操作时,我收到以下异常:
I was a bit too positive. The suggestion below works only in a test program. When doing it in my original code i get following exception:
Attempted to associate a different object with id 'TrackDatas/3452'这是由以下代码生成的:
This is produced by following code:
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 对象.
I am first looking up a song in the database and get a TrackData object in dbTracks.
track 对象也是 TrackData 类型,我只是将刚刚检索到的对象的 ID 放入并尝试存储它,这会导致上述错误.
The track object is also of type TrackData and i just put the ID from the object just retrieved and try to store it, which gives the above error.
我认为上面的消息告诉我对象是不同类型的,而它们不是.
I would think that the above message tells me that the objects are of different types, which they aren't.
如果我使用 AutoMapper,也会发生同样的错误.
The same error happens, if i use AutoMapper.
有什么想法吗?
推荐答案您可以执行您正在尝试的操作:仅使用 ID 替换现有对象.如果它不起作用,您可能做错了其他事情.(在这种情况下,请向我们展示您的代码.)
You can do what you're trying: replace an existing object using just the ID. If it's not working, you might be doing something else wrong. (In which case, please show us your code.)
在 Raven 中更新现有对象时,有几个选项:
When it comes to updating existing objects in Raven, there are a few options:
选项 1:使用与现有对象相同的 ID 保存对象:
Option 1: Just save the object using the same ID as an existing object:
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:手动更新现有对象的属性.
Option 2: Manually update the properties of the existing object.
var song = ...; var existingSong = DbSession.Load<Song>("Songs/5"); existingSong.Artist = song.Artist; existingSong.Album = song.Album;选项 3:动态更新现有对象:
Option 3: Dynamically update the existing object:
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 这样的库.
If you find yourself having to do this often, use a library like AutoMapper.
Automapper 可以用一行代码自动将一个对象复制到另一个对象.
Automapper can automatically copy one object to another with a single line of code.
更多推荐
使用外部对象更新文档
发布评论