我们遇到了一个问题,其中查询乌鸦数据库的以下方法有效,但只有大约90%的时间
member.UserId = userService.GivenUsernameGetUserId(command.EmailAddress.ToLower());
为了抵消这一点,我做了这个丑陋的黑客解决方法似乎解决了这个问题:
member.UserId = userService.GivenUsernameGetUserId(command.EmailAddress.ToLower());
System.Threading.Thread.Sleep(1000);
if (member.UserId.IsNullOrEmpty())
{
logger.Error("the userid was not loaded in time");
for (int i = 0; i < 5; i++)
{
member.UserId = userService.GivenUsernameGetUserId(command.EmailAddress.ToLower());
System.Threading.Thread.Sleep(1000);
if (member.UserId.IsNotNullOrEmpty())
{
logger.Info("The userid was retrieved in a loop after some delay ");
break;
}
}
if (member.UserId.IsNullOrEmpty())
{
logger.Error("a loop of 5 cycles was run trying to retrieve the userId but couldn't get it.");
}
}
任何人都可以看到为什么它有时可能只是检索正确的数据,是否有一个更优雅的解决方案,以确保它继续尝试,直到它检索数据?我在想是否可以在web.config中设置一些基本的超时设置?
答案 0 :(得分:2)
问题可能是陈旧的索引:最近创建了用户,索引没有机会更新。 (通常这需要几毫秒,但在大型数据库上可能需要更长时间。)
您可以在此处执行3项操作来解决问题:
我将在下面描述以下每个选项:
选项1:
让您的用户ID众所周知,这样您就不必拥有用户索引了。
假设您的对象名为User。注册用户时,您的代码将如下所示:
public void RegisterUser(string emailAddress)
{
var user = new User
{
UserName = emailAddress,
...
};
// Give the User a well-known ID, so that we don't have to mess with indexes later.
user.Id = "Users/" + emailAddress;
ravenSession.Store(user);
}
如果你这样做,你根本不必乱用索引。到了加载用户的时候:
public string GivenUsernameGetUserId(string userName)
{
// Look ma, no query needed.
return "Users/" + userName;
// Or, need to return the User itself? You can use .Load, which will never be stale.
// return ravenSession.Load<User>("Users/" + userName);
}
这真的是你最好的选择,你永远不必处理索引,因此,你永远不必处理过时的数据。
选项2
选项2是使用.WaitForNonStaleResults。它会在返回结果之前等待索引变为最新。
public string GivenUsernameGetUserId(string userName)
{
// Use .WaitForNonStaleResultsAsOfNow()
return ravenSession.Query<User>()
.Customize(x => x.WaitForNonStaleResultsAsOfNow())
.Where(u => u.UserName == userName)
.Select(u => u.Id)
.FirstOrDefault();
}
选项3
选项3是在保存用户时等待索引更新。
这需要Raven 3.5或更高版本。
public void RegisterUser(string userName)
{
ravenSession.Advanced.WaitForIndexesAfterSaveChanges(timeout: TimeSpan.FromSeconds(30));
var user = new User {...};
ravenSession.Store(user);
ravenSession.SaveChanges(); // This won't return until the User is stored *AND* the indexes are updated.
};
就个人而言,我建议您为用户使用#1:众所周知的ID。此外,即使您实现其他解决方案,我也建议使用#3:SaveChanges将在返回之前等待索引更新。这将导致陈旧索引周围的意外减少,因此我建议一般。
答案 1 :(得分:0)
我正在使用Raven DB 3.5,并使用提到的选项3
确实可以,但是使用这种方法遇到了一个问题:
在特定的用例中,此操作大约需要60秒钟才能完成。
我不建议一般使用WaitForIndexesAfterSaveChanges()
,因为它显然会导致巨大的性能问题。
相反,我将使用WaitForNonStaleResultsAsOfNow()
配置查询。