feat: 完成agent接口
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||||
|
|
||||||
|
public class AgentResultOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 类型
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public AgentResultTypeEnum TypeEnum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 类型
|
||||||
|
/// </summary>
|
||||||
|
public string Type => TypeEnum.GetJsonName();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内容载体
|
||||||
|
/// </summary>
|
||||||
|
public object Content { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AgentResultTypeEnum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文本内容
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("text")]
|
||||||
|
Text,
|
||||||
|
/// <summary>
|
||||||
|
/// 工具调用中
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("toolCalling")]
|
||||||
|
ToolCalling,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 工具调用完成
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("toolCalled")]
|
||||||
|
ToolCalled,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用量
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("usage")]
|
||||||
|
Usage
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentResultTypeEnumExtensions
|
||||||
|
{
|
||||||
|
public static string GetJsonName(this AgentResultTypeEnum value)
|
||||||
|
{
|
||||||
|
var member = typeof(AgentResultTypeEnum).GetMember(value.ToString()).FirstOrDefault();
|
||||||
|
var attr = member?.GetCustomAttribute<JsonPropertyNameAttribute>();
|
||||||
|
return attr?.Name ?? value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||||
|
|
||||||
|
public class AgentSendInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 会话id
|
||||||
|
/// </summary>
|
||||||
|
public Guid SessionId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户内容
|
||||||
|
/// </summary>
|
||||||
|
public string Content { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// api密钥Id
|
||||||
|
/// </summary>
|
||||||
|
public Guid TokenId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模型id
|
||||||
|
/// </summary>
|
||||||
|
public string ModelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 已选择工具
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Tools { get; set; }
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ using OpenAI.Chat;
|
|||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
using Volo.Abp.Users;
|
using Volo.Abp.Users;
|
||||||
using Yi.Framework.AiHub.Application.Contracts.Dtos;
|
using Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||||
|
using Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||||
using Yi.Framework.AiHub.Domain;
|
using Yi.Framework.AiHub.Domain;
|
||||||
using Yi.Framework.AiHub.Domain.Entities;
|
using Yi.Framework.AiHub.Domain.Entities;
|
||||||
using Yi.Framework.AiHub.Domain.Entities.Model;
|
using Yi.Framework.AiHub.Domain.Entities.Model;
|
||||||
@@ -145,16 +146,26 @@ public class AiChatService : ApplicationService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 ChatManager
|
//ai网关代理httpcontext
|
||||||
|
await _aiGateWayManager.CompleteChatStreamForStatisticsAsync(_httpContextAccessor.HttpContext, input,
|
||||||
|
CurrentUser.Id, sessionId, null, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Agent 发送消息
|
/// Agent 发送消息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpPost("ai-chat/agent/send")]
|
[HttpPost("ai-chat/agent/send")]
|
||||||
public async Task PostAgentSendAsync()
|
[Authorize]
|
||||||
|
public async Task PostAgentSendAsync([FromBody] AgentSendInput input, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await _chatManager.CompleteChatStreamAsync();
|
await _chatManager.AgentCompleteChatStreamAsync(_httpContextAccessor.HttpContext,
|
||||||
|
input.SessionId,
|
||||||
|
input.Content,
|
||||||
|
input.TokenId,
|
||||||
|
input.ModelId,
|
||||||
|
CurrentUser.GetId(),
|
||||||
|
input.Tools,
|
||||||
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using SqlSugar;
|
||||||
|
using Volo.Abp.Auditing;
|
||||||
|
using Volo.Abp.Domain.Entities;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
|
namespace Yi.Framework.AiHub.Domain.Entities.Chat;
|
||||||
|
|
||||||
|
[SugarTable("Ai_AgentStore")]
|
||||||
|
[SugarIndex($"index_{{table}}_{nameof(SessionId)}",
|
||||||
|
$"{nameof(SessionId)}", OrderByType.Desc
|
||||||
|
)]
|
||||||
|
public class AgentStoreAggregateRoot : FullAuditedAggregateRoot<Guid>
|
||||||
|
{
|
||||||
|
public AgentStoreAggregateRoot()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionId"></param>
|
||||||
|
public AgentStoreAggregateRoot(Guid sessionId)
|
||||||
|
{
|
||||||
|
SessionId = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 会话id
|
||||||
|
/// </summary>
|
||||||
|
public Guid SessionId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存储
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)]
|
||||||
|
public string? Store { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置存储
|
||||||
|
/// </summary>
|
||||||
|
public void SetStore()
|
||||||
|
{
|
||||||
|
this.Store = Store;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -234,7 +234,7 @@ public class AiGateWayManager : DomainService
|
|||||||
tokenUsage = data.Usage;
|
tokenUsage = data.Usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = System.Text.Json.JsonSerializer.Serialize(data, ThorJsonSerializer.DefaultOptions);
|
var message = JsonSerializer.Serialize(data, ThorJsonSerializer.DefaultOptions);
|
||||||
backupSystemContent.Append(data.Choices.FirstOrDefault()?.Delta.Content);
|
backupSystemContent.Append(data.Choices.FirstOrDefault()?.Delta.Content);
|
||||||
// 将消息加入队列而不是直接写入
|
// 将消息加入队列而不是直接写入
|
||||||
messageQueue.Enqueue($"data: {message}\n\n");
|
messageQueue.Enqueue($"data: {message}\n\n");
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Dm.util;
|
using Dm.util;
|
||||||
using Microsoft.Agents.AI;
|
using Microsoft.Agents.AI;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.AI;
|
using Microsoft.Extensions.AI;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -12,7 +14,14 @@ using ModelContextProtocol.Server;
|
|||||||
using OpenAI;
|
using OpenAI;
|
||||||
using OpenAI.Chat;
|
using OpenAI.Chat;
|
||||||
using OpenAI.Responses;
|
using OpenAI.Responses;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
using Volo.Abp.Domain.Services;
|
using Volo.Abp.Domain.Services;
|
||||||
|
using Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||||
|
using Yi.Framework.AiHub.Domain.AiGateWay;
|
||||||
|
using Yi.Framework.AiHub.Domain.Entities.Chat;
|
||||||
|
using Yi.Framework.AiHub.Domain.Entities.OpenApi;
|
||||||
|
using Yi.Framework.AiHub.Domain.Shared.Dtos.OpenAi;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
namespace Yi.Framework.AiHub.Domain.Managers;
|
namespace Yi.Framework.AiHub.Domain.Managers;
|
||||||
|
|
||||||
@@ -20,58 +29,136 @@ public class ChatManager : DomainService
|
|||||||
{
|
{
|
||||||
private readonly AiGateWayManager _aiGateWayManager;
|
private readonly AiGateWayManager _aiGateWayManager;
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
|
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
||||||
|
private readonly ISqlSugarRepository<AgentStoreAggregateRoot> _agentStoreRepository;
|
||||||
|
private readonly ISqlSugarRepository<TokenAggregateRoot> _tokenRepository;
|
||||||
|
|
||||||
public ChatManager(AiGateWayManager aiGateWayManager, ILoggerFactory loggerFactory)
|
public ChatManager(AiGateWayManager aiGateWayManager, ILoggerFactory loggerFactory,
|
||||||
|
ISqlSugarRepository<MessageAggregateRoot> messageRepository,
|
||||||
|
ISqlSugarRepository<AgentStoreAggregateRoot> agentStoreRepository,
|
||||||
|
ISqlSugarRepository<TokenAggregateRoot> tokenRepository)
|
||||||
{
|
{
|
||||||
_aiGateWayManager = aiGateWayManager;
|
_aiGateWayManager = aiGateWayManager;
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
|
_messageRepository = messageRepository;
|
||||||
|
_agentStoreRepository = agentStoreRepository;
|
||||||
|
_tokenRepository = tokenRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task CompleteChatStreamAsync()
|
public async Task AgentCompleteChatStreamAsync(HttpContext httpContext,
|
||||||
|
Guid sessionId,
|
||||||
|
string content,
|
||||||
|
Guid tokenId,
|
||||||
|
string modelId,
|
||||||
|
Guid userId,
|
||||||
|
List<string> tools
|
||||||
|
, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
//token可以用户传进来
|
|
||||||
// HttpClient.DefaultProxy = new WebProxy("127.0.0.1:8888");
|
// HttpClient.DefaultProxy = new WebProxy("127.0.0.1:8888");
|
||||||
var modelId = "gpt-5.2";
|
var response = httpContext.Response;
|
||||||
var client = new OpenAIClient(new ApiKeyCredential("xxx"),
|
// 设置响应头,声明是 SSE 流
|
||||||
|
response.ContentType = "text/event-stream;charset=utf-8;";
|
||||||
|
response.Headers.TryAdd("Cache-Control", "no-cache");
|
||||||
|
response.Headers.TryAdd("Connection", "keep-alive");
|
||||||
|
|
||||||
|
//token状态检查,在应用层统一处理
|
||||||
|
var token = await _tokenRepository.GetFirstAsync(x => x.Id == tokenId);
|
||||||
|
var client = new OpenAIClient(new ApiKeyCredential(token.Token),
|
||||||
new OpenAIClientOptions
|
new OpenAIClientOptions
|
||||||
{
|
{
|
||||||
Endpoint = new Uri("https://yxai.chat/v1"),
|
Endpoint = new Uri("https://yxai.chat/v1"),
|
||||||
});
|
});
|
||||||
|
|
||||||
var agent = client.GetChatClient(modelId)
|
var agent = client.GetChatClient(modelId)
|
||||||
.CreateAIAgent("你是一个专业的网页ai助手");
|
.CreateAIAgent("你是一个专业的网页ai助手,擅长解答用户问题");
|
||||||
|
|
||||||
|
//线程根据sessionId数据库中获取
|
||||||
|
var agentStore =
|
||||||
|
await _agentStoreRepository.GetFirstAsync(x => x.SessionId == sessionId);
|
||||||
|
if (agentStore is null)
|
||||||
|
{
|
||||||
|
agentStore = new AgentStoreAggregateRoot(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取当前线程
|
||||||
|
AgentThread currentThread;
|
||||||
|
if (!string.IsNullOrWhiteSpace(agentStore.Store))
|
||||||
|
{
|
||||||
|
//获取当前存储
|
||||||
|
JsonElement reloaded = JsonSerializer.Deserialize<JsonElement>(agentStore.Store, JsonSerializerOptions.Web);
|
||||||
|
currentThread = agent.DeserializeThread(reloaded, JsonSerializerOptions.Web);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentThread = agent.GetNewThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var thread = agent.GetNewThread();
|
var toolContents = GetTools();
|
||||||
|
|
||||||
var tools = GetTools();
|
|
||||||
var chatOptions = new ChatOptions()
|
var chatOptions = new ChatOptions()
|
||||||
{
|
{
|
||||||
Tools = tools.Select(x => (AITool)x).ToList(),
|
Tools = toolContents.Select(x => (AITool)x).ToList(),
|
||||||
ToolMode = ChatToolMode.Auto
|
ToolMode = ChatToolMode.Auto
|
||||||
};
|
};
|
||||||
|
|
||||||
await foreach (var update in agent.RunStreamingAsync("联网搜索一下,奥德赛第一中学学生会会长是谁", thread,
|
await foreach (var update in agent.RunStreamingAsync(content, currentThread, new ChatClientAgentRunOptions(chatOptions), cancellationToken))
|
||||||
new ChatClientAgentRunOptions(chatOptions)))
|
|
||||||
{
|
{
|
||||||
// 检查每个更新中的内容
|
// 检查每个更新中的内容
|
||||||
foreach (var content in update.Contents)
|
foreach (var updateContent in update.Contents)
|
||||||
{
|
{
|
||||||
switch (content)
|
switch (updateContent)
|
||||||
{
|
{
|
||||||
|
//工具调用中
|
||||||
case FunctionCallContent functionCall:
|
case FunctionCallContent functionCall:
|
||||||
Console.WriteLine();
|
await SendHttpStreamMessageAsync(httpContext,
|
||||||
Console.WriteLine(
|
new AgentResultOutput
|
||||||
$"🔧 工具调用开始: {functionCall.CallId},{functionCall.Name},{functionCall.Arguments}");
|
{
|
||||||
|
TypeEnum = AgentResultTypeEnum.ToolCalling,
|
||||||
|
Content = functionCall.Name
|
||||||
|
},
|
||||||
|
isDone: false, cancellationToken);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//工具调用完成
|
||||||
case FunctionResultContent functionResult:
|
case FunctionResultContent functionResult:
|
||||||
Console.WriteLine();
|
await SendHttpStreamMessageAsync(httpContext,
|
||||||
Console.WriteLine($"✅ 工具调用完成: {functionResult.CallId},{functionResult.Result}");
|
new AgentResultOutput
|
||||||
|
{
|
||||||
|
TypeEnum = AgentResultTypeEnum.ToolCalled,
|
||||||
|
Content = functionResult.Result
|
||||||
|
},
|
||||||
|
isDone: false, cancellationToken);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//内容输出
|
||||||
case TextContent textContent:
|
case TextContent textContent:
|
||||||
Console.Write($"{textContent.Text}");
|
//发送消息给前端
|
||||||
|
await SendHttpStreamMessageAsync(httpContext,
|
||||||
|
new AgentResultOutput
|
||||||
|
{
|
||||||
|
TypeEnum = AgentResultTypeEnum.Text,
|
||||||
|
Content = textContent.Text
|
||||||
|
},
|
||||||
|
isDone: false, cancellationToken);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//用量统计
|
||||||
case UsageContent usageContent:
|
case UsageContent usageContent:
|
||||||
|
//存储message 为了token算费
|
||||||
|
await SendHttpStreamMessageAsync(httpContext,
|
||||||
|
new AgentResultOutput
|
||||||
|
{
|
||||||
|
TypeEnum = AgentResultTypeEnum.Usage,
|
||||||
|
Content = new ThorUsageResponse
|
||||||
|
{
|
||||||
|
InputTokens = Convert.ToInt32(usageContent.Details.InputTokenCount ?? 0),
|
||||||
|
OutputTokens = Convert.ToInt32(usageContent.Details.OutputTokenCount ?? 0),
|
||||||
|
TotalTokens = usageContent.Details.TotalTokenCount ?? 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isDone: false, cancellationToken);
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine($"✅ 用量统计: {usageContent.Details.TotalTokenCount}");
|
Console.WriteLine($"✅ 用量统计: {usageContent.Details.TotalTokenCount}");
|
||||||
break;
|
break;
|
||||||
@@ -79,10 +166,15 @@ public class ChatManager : DomainService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//断开连接
|
||||||
|
await SendHttpStreamMessageAsync(httpContext, null, isDone: true, cancellationToken);
|
||||||
|
|
||||||
string serializedJson = thread.Serialize(JsonSerializerOptions.Web).GetRawText();
|
//将线程持久化到数据库
|
||||||
JsonElement reloaded = JsonSerializer.Deserialize<JsonElement>(serializedJson, JsonSerializerOptions.Web);
|
string serializedJson = currentThread.Serialize(JsonSerializerOptions.Web).GetRawText();
|
||||||
var newThread = agent.DeserializeThread(reloaded, JsonSerializerOptions.Web);
|
agentStore.Store = serializedJson;
|
||||||
|
|
||||||
|
//插入或者更新
|
||||||
|
await _agentStoreRepository.InsertOrUpdateAsync(agentStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -106,4 +198,32 @@ public class ChatManager : DomainService
|
|||||||
|
|
||||||
return mcpTools;
|
return mcpTools;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext"></param>
|
||||||
|
/// <param name="content"></param>
|
||||||
|
/// <param name="isDone"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task SendHttpStreamMessageAsync(HttpContext httpContext,
|
||||||
|
AgentResultOutput? content,
|
||||||
|
bool isDone = false,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var response = httpContext.Response;
|
||||||
|
string output;
|
||||||
|
if (isDone)
|
||||||
|
{
|
||||||
|
output = "[DONE]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output = JsonSerializer.Serialize(content,ThorJsonSerializer.DefaultOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
await response.WriteAsync($"data: {output}\n\n", Encoding.UTF8, cancellationToken).ConfigureAwait(false);
|
||||||
|
await response.Body.FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.Mapster\Yi.Framework.Mapster.csproj" />
|
<ProjectReference Include="..\..\..\framework\Yi.Framework.Mapster\Yi.Framework.Mapster.csproj" />
|
||||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
|
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\Yi.Framework.AiHub.Application.Contracts\Yi.Framework.AiHub.Application.Contracts.csproj" />
|
||||||
<ProjectReference Include="..\Yi.Framework.AiHub.Domain.Shared\Yi.Framework.AiHub.Domain.Shared.csproj" />
|
<ProjectReference Include="..\Yi.Framework.AiHub.Domain.Shared\Yi.Framework.AiHub.Domain.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ namespace Yi.Abp.Web
|
|||||||
var app = context.GetApplicationBuilder();
|
var app = context.GetApplicationBuilder();
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<ActivationCodeAggregateRoot>();
|
//app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<AgentStoreAggregateRoot>();
|
||||||
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<ActivationCodeRecordAggregateRoot>();
|
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<ActivationCodeRecordAggregateRoot>();
|
||||||
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<UsageStatisticsAggregateRoot>();
|
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<UsageStatisticsAggregateRoot>();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user