Ravendb 使用外部对象更新文档

Ravendb 使用外部对象更新文档,ravendb,Ravendb,我有一个包含歌曲对象的数据库。song类具有>30个属性 我的音乐标签应用程序正在文件系统中对歌曲进行更改。 然后,它使用文件名在数据库中进行查找 现在我有了一个Song对象,它是我在标记应用程序中通过读取物理文件创建的,我还有一个Song对象,我刚从数据库中检索到,我想更新它。 我想我可以从数据库对象中获取ID,用本地歌曲对象替换数据库对象,设置保存的ID并存储它。 但是Raven声称我正在用一个不同的对象替换这个对象 我真的需要像这样复制每一处房产吗 dbSong.Artist=songfr

我有一个包含歌曲对象的数据库。song类具有>30个属性

我的音乐标签应用程序正在文件系统中对歌曲进行更改。 然后,它使用文件名在数据库中进行查找

现在我有了一个Song对象,它是我在标记应用程序中通过读取物理文件创建的,我还有一个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);
  }
试试看
{
originalFileName=Util.EscapeDatabaseQuery(originalFileName);
//在数据库中查找轨迹
var dbTracks=_session.Advanced.DocumentQuery().WhereEquals(“Query”,originalFileName).ToList();
如果(dbTracks.Count>0)
{
track.Id=dbTracks[0].Id;
_session.Store(track);
_session.SaveChanges();
}
}
捕获(例外情况除外)
{
Error(“UpdateTrack:更新数据库{0}:{1}中的跟踪时出错”,例如Message,例如InnerException);
}
我首先在数据库中查找一首歌曲,然后在dbTracks中获得一个TrackData对象

track对象也是TrackData类型,我只是将刚检索到的对象的ID放入并尝试存储它,这就产生了上述错误

我认为上面的消息告诉我对象是不同类型的,而它们不是

如果我使用AutoMapper,同样的错误也会发生


有什么想法吗?

您可以做您正在尝试的事情:仅使用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
var song = ...;
var existingSong = DbSession.Load<Song>("Songs/5");
existingSong.CopyFrom(song);
选项2:手动更新现有对象的属性

var song = ...;
var existingSong = DbSession.Load<Song>("Songs/5");
existingSong.Artist = song.Artist;
existingSong.Album = song.Album;
如果您发现自己不得不经常这样做,请使用类似的库


Automapper可以用一行代码自动将一个对象复制到另一个对象。

现在您已经发布了一些代码,我看到了两件事:

首先,使用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();
//这是高级查询语法。你使用它有什么原因吗?
var dbTracks=_session.Advanced.DocumentQuery().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();
}
var escapedFileName=Util.EscapeDatabaseQuery(originalFileName);
//在数据库中查找现有曲目的ID。
var existingTrackId=\u session.Query()
.Where(t=>t.Query==转义文件名)
.选择(t=>t.Id);
if(existingTrackId!=null)
{
track.Id=现有trackid;
_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();
}
var escapedFileName=Util.EscapeDatabaseQuery(originalFileName);
//在数据库中查找现有曲目的ID。
var existingTrackId=\u session.Query()
.Where(t=>t.Query==转义文件名)
.选择(t=>t.Id);
if(existingTrackId!=null)
{
var newTrack=新轨道(…);
newTrack.Id=现有TrackID;
_会话存储(newTrack);
_session.SaveChanges();
}

这意味着会话中已存在具有相同id的不同对象。我的解决方法是使用新会话。

非常感谢您的回答。我尝试了以上所有的可能性,包括Automapper。发现我把身份证设置错了。我很乐意帮忙。如果你能将此作为答案,我将不胜感激。谢谢仍然有错误。使用附加信息更改了我的原始帖子。track是TrackData的一个对象,它是通过从例如mp3文件中读取标签信息创建的。它包含对音乐文件所做的更改。并且更改应该存储在数据库中。我明天就用你的LINQ语法试试。这能解决你的问题吗,@Helmut?na,我想做什么就做什么。我用的是你上面的结构。正在创建一个新的TrackData对象,并使用了一个现有id。store命令给出了上述错误。唯一有效的方法是,如果我从数据库加载对象,将每个属性分配给加载的db对象,然后存储db对象。即使使用AutoMapper也不起作用。我不知道可能是什么问题。您是否在任何地方设置了。使用OptimisticConcurrency?如果是,您将其设置为什么?
 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();
}