我从Guid转移到RavenDb docs建议的字符串(HiLo)键。 我的一些DomainEvent在构造函数中被触发,因此在触发事件之前应该知道Id。当我使用Guid时,我只是创建Guid.NewGuid()来生成Id。但对于RavenDb提供的HiLo,我所做的是为我生成密钥的扩展方法,然后作为参数传递给我的Entity构造函数。
RavenDb版本:RavenDb.Client 3.0.30000
Note that this is a copy-paste code I found on the internet :)
public static class RavenDbExtensions
{
public static string GenerateIdFor<T>(this IDocumentSession session)
{
// We need the advanced session in order to ensure that the keys are generated in the correct database.
// session.Advanced.DocumentStore.DatabaseCommands is not sufficient.
var advancedSession = session.Advanced as DocumentSession;
if (advancedSession == null)
throw new InvalidOperationException();
// An entity instance is required to generate a key, but we only have a type.
// In our case, the entities don't have public constructors so we must use reflection.
var entity = Activator.CreateInstance(typeof(T), true);
// Generate an ID using the commands and conventions from the current session
return advancedSession.Conventions.GenerateDocumentKey(
advancedSession.DocumentStore.Identifier,
advancedSession.DatabaseCommands,
entity);
}
}
我的控制器方法。
[HttpPost]
[ValidateAntiForgeryToken]
[Route("add", Name = "courses.add")]
public ActionResult Add(AddViewModel model)
{
if (!ModelState.IsValid)
{
model.Categories = DocumentSession.Query<Category>().ToList();
return View(model);
}
string courseId = DocumentSession.GenerateIdFor<Course>();
var course = Course.Create(
courseId,
model.Title,
CourseCode.FromString(model.Code),
StandardDuration.Create(model.Days, model.HoursPerDay),
model.StandardPrice,
model.CategoryId);
DocumentSession.Store(course);
return RedirectToAction("Add");
}
我的这个类有JsonIgnore (Raven.Imports.Newtonsoft.Json)
属性
public class StandardDuration : ValueObject
{
private StandardDuration(int days, int hoursPerDay)
{
Days = days;
HoursPerDay = hoursPerDay;
}
public int Days { get; private set; }
public int HoursPerDay { get; private set; }
public static StandardDuration Create(int days, int hoursPerDay)
{
if (days <= 0)
throw new DomainModelException("Days should be atleast one");
if (hoursPerDay <= 0)
throw new DomainModelException("CreditHours should be greater than zero");
return new StandardDuration(days, hoursPerDay);
}
[JsonIgnore]
public int CreditHours
{
get { return HoursPerDay * Days; }
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Days;
yield return HoursPerDay;
}
}
会抛出错误
Attempt by method 'Raven.Client.Document.DocumentConvention.DefaultTypeTagName(System.Type)' to access method 'Raven.Imports.Newtonsoft.Json.Utilities.TypeExtensions.IsGenericType(System.Type)' failed.
更新
由于相同的问题但在显示页面之前,我无法重现上述代码中的错误。
但即使在non JsonIgnore decorated
课程上我也面临同样的问题。
public class Category : Entity
{
private Category() { }
private Category(Guid id, string name)
{
Id = id;
Name = name;
}
public string Name { get; private set; }
public static Category Create(Guid id, string name)
{
if (string.IsNullOrWhiteSpace(name))
throw new DomainModelException("Category name should not be blank or null.");
return new Category(id, name);
}
}
控制器操作
[HttpPost]
[Route("add", Name = "course_categories.add")]
public ActionResult Add(string name)
{
if (ModelState.IsValid)
{
var courseCategory = Category.Create(Guid.NewGuid(), name);
DocumentSession.Store(courseCategory);
AddSuccessMessage("Course Category created");
return RedirectToRoute("course_categories.add_page");
}
ModelState.AddModelError("", "An error occurred please try again.");
return View();
}
堆栈跟踪:
[MethodAccessException: Attempt by method 'Raven.Client.Document.DocumentConvention.DefaultTypeTagName(System.Type)' to access method 'Raven.Imports.Newtonsoft.Json.Utilities.TypeExtensions.IsGenericType(System.Type)' failed.]
Raven.Client.Document.DocumentConvention.DefaultTypeTagName(Type t) in c:\Builds\RavenDB-Stable-3.0\Raven.Client.Lightweight\Document\DocumentConvention.cs:264
Raven.Client.Document.DocumentConvention.GetTypeTagName(Type type) in c:\Builds\RavenDB-Stable-3.0\Raven.Client.Lightweight\Document\DocumentConvention.cs:296
Raven.Client.Document.DocumentConvention.DefaultFindFullDocumentKeyFromNonStringIdentifier(Object id, Type type, Boolean allowNull) in c:\Builds\RavenDB-Stable-3.0\Raven.Client.Lightweight\Document\DocumentConvention.cs:152
Raven.Client.Document.GenerateEntityIdOnTheClient.GetIdAsString(Object entity, Object value, String& id) in c:\Builds\RavenDB-Stable-3.0\Raven.Client.Lightweight\Document\GenerateEntityIdOnTheClient.cs:49
Raven.Client.Document.GenerateEntityIdOnTheClient.TryGetIdFromInstance(Object entity, String& id) in c:\Builds\RavenDB-Stable-3.0\Raven.Client.Lightweight\Document\GenerateEntityIdOnTheClient.cs:33
Raven.Client.Document.InMemoryDocumentSessionOperations.Store(Object entity) in c:\Builds\RavenDB-Stable-3.0\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:646
Web.Features.CourseCategories.CourseCategoriesController.Add(String name) in E:\Projects\Akademia\Presentation\Web\Features\CourseCategories\CourseCategoriesController.cs:39
lambda_method(Closure , ControllerBase , Object[] ) +104
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +157
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9721605
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155