obase社区Obase开发者QQ群:962698871
obase

欢迎查阅
OBASE帮助文档

本节内容对应的Demo位于Obase.Test.Demo中Obase.Test/Expert,Obase.Test.Infrastructure/Expert和Obase.Test.Domain内,所使用的数据库表建表脚本(MySql版)位于Obase.Test.Infrastructure内。

上下文配置提供程序

此前我们已经配置过诸多的上下文配置提供程序,这里提供一个重写了所有可重写的属性和方法的上下文提供程序实例。

/// <summary>
///     重写所有可重写的Sql上下文配置提供程序
/// </summary>
public class FullSqlContextConfiger : SqlContexConfiger
{
    /// <summary>
    ///     获取特定于数据库服务器(SQL Server、Oracle等)的数据提供程序工厂
    /// </summary>
    protected override DbProviderFactory DbProviderFactory { get; }

    /// <summary>
    ///     连接字符串
    /// </summary>
    protected override string ConnectionString { get; }

    /// <summary>
    ///     获取一个值,该值指示是否自动创建对象集。
    /// </summary>
    protected override bool WhetherCreateSet { get; }

    /// <summary>
    ///     显式指示数据源的类型
    /// </summary>
    protected override eDataSource SourceType { get; }

    /// <summary>
    ///     使用指定的建模器创建对象数据模型。
    /// </summary>
    /// <param name="modelBuilder"></param>
    protected override void CreateModel(ModelBuilder modelBuilder)
    {
    }

    /// <summary>
    ///     获取映射模块。
    /// </summary>
    /// <returns>
    ///     如果要扩展映射管道时,返回映射模块序列;否则返回null。
    /// </returns>
    protected override IMappingModule[] GetMappingModules()
    {
        return null;
    }

    /// <summary>
    ///     获取用于发送对象变更通知的消息队列。
    /// </summary>
    /// <returns>如果要发送对象变更通知,返回一个消息队列实例;否则返回null。</returns>
    protected override IMessageQueue GetNoticeQueue()
    {
        return null;
    }
}

详细的内容会在之后的对象上下文一章中加以详细介绍。

更改通知

我们可以通过实现IMessageQueue并在对象上下文提供者中返回其实例并为某个实体型配置要通知的动作而实现更改通知。

/// <summary>
///     表示学生
/// </summary>
public class Student
{

    /// <summary>
    ///     学生名称
    /// </summary>
    private string _name;


    /// <summary>
    ///     学生id
    /// </summary>
    private long _studentId;

    /// <summary>
    ///     学生id
    /// </summary>
    public long StudentId
    {
        get => _studentId;
        set => _studentId = value;
    }

    /// <summary>
    ///     学生名称
    /// </summary>
    public string Name
    {
        get => _name;
        set => _name = value;
    }

    /// <summary>
    ///     转换为字符串表示形式
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return $"Student:{{StudentId-{_studentId},Name-\"{_name}\"}}";
    }
}

以上代码为用于演示的学生类。

/// <summary>
///     消息队列 用于发送/接收消息
/// </summary>
public class MessageQueue : IMessageQueue
{
    /// <summary>
    ///     用于模拟消息队列的Txt文件路径
    /// </summary>
    private readonly string _path;

    /// <summary>
    ///     构造消息队列对象
    /// </summary>
    public MessageQueue()
    {
        _path = $"{Directory.GetCurrentDirectory()}\\TestQueue.txt";
    }

    /// <summary>
    ///     用字节序列的形式将消息发送至消息队列。
    /// </summary>
    /// <param name="msg">要发送的消息对象。</param>
    public void SendMessage(byte[] msg)
    {
        var fileStream = new FileStream(_path, FileMode.OpenOrCreate);
        var writer = new StreamWriter(fileStream);
        writer.WriteLine(Convert.ToBase64String(msg));
        writer.Flush();
        writer.Close();
    }

    /// <summary>
    ///     用字符序列的形式将消息发送至消息队列。
    /// </summary>
    /// <param name="msg">要发送的消息对象。</param>
    public void SendMessage(string msg)
    {
        var bytes = Encoding.UTF8.GetBytes(msg);
        SendMessage(bytes);
    }
}

以上为实现了IMessageQueue的MessageQueue。

//注册学生实体
var studentConfiguration = modelBuilder.Entity<Student>();
//配置要通知的属性
studentConfiguration.HasNoticeAttributes(new List<string>() {"Name"});
//是否在创建时通知
studentConfiguration.HasNotifyCreation(true);
//是否在修改时通知
studentConfiguration.HasNotifyUpdate(true);
//是否在删除时通知
studentConfiguration.HasNotifyDeletion(true);

以上为更改通知的配置。 详细的内容会在之后的更改通知一章中加以详细介绍。

映射模块

映射模块是Obase的重要扩展机制,实现IMappingModule接口可以实现自定义的映射模块,订阅Obase内部的多个映射管道中的事件实现自定义的功能。

/// <summary>
///     映射模块
/// </summary>
public class MappingModule : IMappingModule
{
    /// <summary>初始化映射模块。</summary>
    /// <param name="savingPipeline">"保存"管道。</param>
    /// <param name="deletingPipeline">"删除"管道。</param>
    /// <param name="queryPipeline">"查询"管道。</param>
    /// <param name="directlyChangingPipeline">"就地修改"管道。</param>
    public void Init(ISavingPipeline savingPipeline, IDeletingPipeline deletingPipeline, IQueryPipeline queryPipeline,
        IDirectlyChangingPipeline directlyChangingPipeline)
    {
        queryPipeline.PostExecuteCommand += QueryPipelineOnPostExecuteCommand;
    }

    /// <summary>
    ///     处理PostExecuteCommand
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void QueryPipelineOnPostExecuteCommand(object sender, PostExecuteCommandEventArgs e)
    {
        //查询的PostExecuteCommand传来的Command为QuerySql
        Console.WriteLine(((QuerySql)e.Command).ToSql(eDataSource.MySql));
    }
}

在对象上下文配置提供者中如下配置即可

/// <summary>获取映射模块。</summary>
/// <returns>如果要扩展映射管道时,返回映射模块序列;否则返回null。</returns>
protected override IMappingModule[] GetMappingModules()
{
    return new IMappingModule[] { new MappingModule() };
}

详细的内容会在之后的映射模块一章中加以详细介绍。

乐观并发模型

Obase定义了三种并发冲突:重复创建,版本冲突,更新幻影。并使用五种策略来应对他们,分别是:忽略,引发异常,强制覆盖,版本合并和重建对象。 我们以如下的类作为乐观并发模型的示例:

/// <summary>
///     带有版本键的键值对
/// </summary>
public class KeyValueWithVersion
{
    /// <summary>
    ///     唯一标识
    /// </summary>
    private int _id;

    /// <summary>
    ///     键
    /// </summary>
    private string _key;

    /// <summary>
    ///     值
    /// </summary>
    private int _value;

    /// <summary>
    ///     版本键
    /// </summary>
    private int _versionKey;

    /// <summary>
    ///     键
    /// </summary>
    public string Key
    {
        get => _key;
        set => _key = value;
    }

    /// <summary>
    ///     值
    /// </summary>
    public int Value
    {
        get => _value;
        set => _value = value;
    }

    /// <summary>
    ///     版本键
    /// </summary>
    public int VersionKey
    {
        get => _versionKey;
        set => _versionKey = value;
    }

    /// <summary>
    ///     唯一标识
    /// </summary>
    public int Id
    {
        get => _id;
        set => _id = value;
    }

    /// <summary>
    ///     返回字符串表示形式
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return $"KeyValueWithVersion:{{Id-{_id},Key-\"{_key}\",Value-{_value},VersionKey-{_versionKey}}}";
    }
}

对应的MySql建表脚本:

DROP TABLE IF EXISTS `keyvalues`;
CREATE TABLE `keyvalues`  (
  `Id` int(11) NOT NULL,
  `Key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `Value` int(255) NULL DEFAULT NULL,
  `VersionKey` int(255) NULL DEFAULT NULL,
  PRIMARY KEY (`Id`) USING BTREE
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin;

使用忽略策略的配置:

//配置版本键和并发处理策略
modelBuilder.Entity<KeyValueWithVersion>()
    .HasKeyAttribute(p => p.Id)
    .HasKeyIsSelfIncreased(false)
    .HasConcurrentConflictHandlingStrategy(eConcurrentConflictHandlingStrategy.Ignore)
    .HasKeyAttribute(p => p.VersionKey).ToTable("KeyValues");

详细的内容会在之后的乐观并发模型一章中加以详细介绍。

没有找到您需要的文档?

您还可以通过人工服务在线咨询,服务时间为每天上午9点至下午6点。

If you can't find required answer, get in touch with us online. We provide service from 9:00 to 18:00.

让编程成为一件快乐的事
现在开始