我有一个使用 EventSourcing 的 DDD 项目。目前有许多聚合根,其中许多都有实体的集合。甚至更多 - 一些实体具有其他实体的集合。
问题:出于审计目的读取 EventSourcing 事件日志。
问题:当实体被更新/创建/删除时,在 EventStore 中保存事件的最佳方法是什么,记住所有这些事情:它们必须易于阅读,版本,可能不适合这种情况,但通常粒度事件更可取,可能域事件将用于跨域通信。
我是否应该在根流中将整个根以及其中的所有实体集合保存为 RootChangedEvent ?
我是否应该只将根流中已更新/创建/删除的实体保存为 EntityChangedEvent/EntityCreatedEvent/EntityRemovedEvent
我应该在根流中保存两个事件 - 一个用于根 - RootChangedEvent 只有版本属性 + 第二个用于实体,如果在 EntityChangedEvent 或整个实体中更改,则只有一个属性,如果 EntityCreatedEvent 或只有 id 如果 EntityRemovedEvent (如何处理实体的实体是否创建/更新/删除?)
这是我项目中的一个例子:
根 - 管道。
public class Pipeline : AggregateRoot<IPipelineState>
Run Code Online (Sandbox Code Playgroud)
它有实体集合 - public IList<Status> Statuses.
每个状态都有实体的集合 - public IList<Logic> Logics。
所有集合都可以存储很多实体。现在我会引发诸如 PipelineCreatedEvent、PipelineChangedEvent 之类的事件(不仅在 Pipeline 更改时,甚至在添加、更新、删除状态或逻辑时)和 PipelineRemovedEvent。
顺便问一下,如何创建 STREAM?
我直接使用 AppendToStreamAsync,这是正确的还是我应该先创建一个流然后附加到该流上?
我还尝试执行一些测试,但使用下面的方法我可以将事件写入 EventStore 但无法从中读取事件。
最重要的问题是如何在 EventStore 的管理站点中查看我的保存事件?
这是代码:
public async Task AppendEventAsync(IEvent @event)
{
try
{
var eventData = new EventData(@event.EventId,
@event.GetType().AssemblyQualifiedName,
true,
Serializer.Serialize(@event),
Encoding.UTF8.GetBytes("{}"));
var writeResult = await connection.AppendToStreamAsync(
@event.SourceId.ToString(),
@event.AggregateVersion,
eventData);
Console.WriteLine(writeResult);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public async Task<IEnumerable<IEvent>> ReadEventsAsync(Guid aggregateId)
{
var ret = new List<IEvent>();
StreamEventsSlice currentSlice;
long nextSliceStart = StreamPosition.Start;
do
{
currentSlice = await connection.ReadStreamEventsForwardAsync(aggregateId.ToString(), nextSliceStart, 200, false);
if (currentSlice.Status != SliceReadStatus.Success)
{
throw new Exception($"Aggregate {aggregateId} …Run Code Online (Sandbox Code Playgroud) 我在我的项目(MVC/web api 等)中使用 serilog & SEQ 和 Autofac (DI)。虽然它工作正常,但不确定这是正确的方法。
我有几个问题。请帮忙
Q1) 如何使 LoggerConfiguration 通过 Web.config (appsetting) 进行管理,例如 Verbose/Debug 等。
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.WriteTo.Seq(serilogUrl)
.CreateLogger();
Run Code Online (Sandbox Code Playgroud)
Q2)对于Everymessage,我想写userid。我已经使用了推送属性,但没有“使用”语句。见下面的代码
public partial class Repo : BaseRepo<db>
{
public Repo(ILogger logger) : base(logger)
{
var currentuser = GetUserName();
LogContext.PushProperty("User Name", currentuser);
Logger.ForContext<Repo>();
}
public void somefunction()
{
try{}
catch(exception e){
Logger.Error(e, "Message");
}
}
}
Run Code Online (Sandbox Code Playgroud)
Q3)在构造函数中,我使用了 Logger.ForContext(),假设这会将类名写入每条消息。但它不起作用。
Logger.ForContext<Repo>()
Run Code Online (Sandbox Code Playgroud)
注意:我没有使用asp.net core/.Net core
在构建事件存储时,典型的方法是序列化事件,然后持久化事件类型、事件主体(序列化事件本身)、标识符和发生时间。
关于事件类型,是否有关于如何存储和引用这些事件的最佳实践?我看到的示例存储类的完全限定路径,即。
com.company.project.package.XXXXEvent
Run Code Online (Sandbox Code Playgroud)
如果您决定重构您的项目结构,那么需要什么努力?
我已经通过代码尝试了用于 Serilog 的 PostgreSQL 接收器,它的工作方式就像一个魅力。
这是工作代码:
static void Main(string[] args)
{
var connectionString = "Server=localhost; Port=5432; Database=subscriptions_log; User Id=postgres;Password=postgres";
string tableName = "errorlog";
IDictionary<string, ColumnWriterBase> columnWriters = new Dictionary<string, ColumnWriterBase>
{
{"message", new RenderedMessageColumnWriter(NpgsqlDbType.Text) },
{"level", new LevelColumnWriter(true, NpgsqlDbType.Varchar) },
{"raise_date", new TimestampColumnWriter(NpgsqlDbType.Timestamp) },
{"exception", new ExceptionColumnWriter(NpgsqlDbType.Text) }
};
using var log = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.PostgreSQL(connectionString, tableName, columnWriters)
.CreateLogger();
log.Information("Hello, Serilog!");
}
Run Code Online (Sandbox Code Playgroud)
但是,当我通过配置文件使用它时,serlig 在数据库中创建表,但由于未找到“Npgsql.NpgsqlBinaryImporter.Complete()”,因此不插入任何行。
“这是详细的错误:
Exception while emitting periodic batch from Serilog.Sinks.PostgreSQL.PostgreSQLSink:
System.MissingMethodException:
Method not found: 'Void Npgsql.NpgsqlBinaryImporter.Complete()'. …Run Code Online (Sandbox Code Playgroud) 如何使用HtmlAgilityPack替换所有超链接,例如:
<a href="url">Link</>
Run Code Online (Sandbox Code Playgroud)
这样只剩下href属性.网址.
这可能吗?
作为使用MSBuild运行xUnit.net测试的一些构建自动化的一部分,我遇到了需要循环遍历一批项目的情况.
在循环内部,我需要检测迭代是否失败,但我想继续执行,无论如何.然后在批处理后,我需要知道是否发生了一个或多个错误,以便向TeamBuild报告结果.
IOW,伪代码:
Task Name=RunTests
CreateItems
ForEach item CallTarget Target=RunTest ContinueOnError=true
CombineNUnitResults
Report success/failure
Task Name=RunTest
XUnit item
Run Code Online (Sandbox Code Playgroud)
我希望这可以在没有自定义任务的情况下实现(或者像Jonne那样攻击xunit.net MSBuild任务).(但愿意使用MSBuild社区或Sdc任务)
和@BradWilson:我不可能干净利落地做,我会在NUnit任务中找到Jonne的变化,也可以让它进入xunit任务
我是设计模式的初学者.
我正在尝试使用抽象工厂模式,同时保持开放封闭原则.
Plz看下面的代码:
public interface IAbstractFormFactory
{
void ShowOSName();
}
public class VistaForm : IAbstractFormFactory
{
public void ShowOSName()
{
Console.WriteLine("Vista");
}
}
public class WinXpForm : IAbstractFormFactory
{
public void ShowOSName()
{
Console.WriteLine("Win XP");
}
}
public static class Application
{
public static void Run(IAbstractFormFactory factory)
{
factory.ShowOSName();
}
}
public class Program
{
public static void Main()
{
IAbstractFormFactory form;
int sys = 0;
if (sys == 0)
{
form = new WinXpForm();
}
else
{
form = …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用.Net 3.5在C#中执行一些基本的AD用户管理任务
我有一个包含用户详细信息的System.DirectoryServices.AccountManagement.UserPrincipal对象.
我可以打电话user.ExpirePasswordNow(),用户将在下次登录时被迫更改密码(并且"Active Directory用户和计算机"GUI具有"用户必须在下次登录时更改密码"复选框.
但是,我想测试这个属性的状态并对它采取行动 - 我不想总是通过ExpirePasswordNow()函数将它设置为true .我怎样才能做到这一点?
我发现了一些示例,建议我访问底层的DirectoryEntry及其pwdLastSet属性 - 但这看起来像一个无法穿透的System .__ ComObject类型 - 它可能是一个IADsLargeInteger,但由于其"保护级别",我无法转换为该类型.
我不知所措 - 有人可以帮忙吗?
我用C++编写了一个向导,它将一些文件安装到windows下的程序文件文件夹中.据我了解,我需要管理员权限写入Vista/7下的程序文件.所以我的问题是:在应用程序分别仅针对一个向导页面运行时,是否有办法打开管理员权限?或者我是否必须为此一个向导页面启动具有管理员权限的另一个进程?
.net ×2
serilog ×2
.net-3.5 ×1
c# ×1
c++ ×1
cross-domain ×1
events ×1
eventstoredb ×1
exit-code ×1
msbuild ×1
team-build ×1
uac ×1
windows-7 ×1
xunit.net ×1