目前 Camstar 开发主要分为两种:1、基于 Designer 的 CLF 编程;2、基于 C# 的程序编程。在 Designer 环境下的 CLF 可以通过(对象实例.字段)的方式快速访问数据,但 Designer 并不是完善的编程工具,不方便调试,没有语法校验等功能,开发效率较低。对于 C# 提供的各种类库,CLF 同样难以调用。而 C# 有强大的生态环境,工具齐全,类库丰富。

为了能在 C# 环境下更便捷地访问 Camstar 对象数据,本项目基于 ORM 构建只读数据访问层(Opcenter.Execution.Data)。本库不开放 SaveChanges 写库。

可选 ORM 很多,综合考虑后选择支持懒加载与对象关系配置的 EF Core 作为首选。

一、项目位置

backend/Opcenter.Execution.Data

配套说明(均在本项目内):

  • README.md:结构与用法总览
  • Docs/repository-api-matrix.md:仓储查询 API 与 CancellationToken 约定

二、使用示例

支持 Oracle 与 SQL Server。通过本项目扩展方法 AddOpcenterExDbServices 注册。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
services.AddOpcenterExDbServices(options =>
{
options.ConnectionString = "...";
options.DatabaseType = DatabaseType.SqlServer; // 或 DatabaseType.Oracle
options.Schema = "CamstarPRD_SCHEMA"; // 可空;Camstar 库常需指定
});

// 按名称查询 NamedDataObject(推荐走仓储)
public class ExampleService(INamedDataObjectRepository<Factory> factories)
{
public async Task<string?> GetEnterpriseNameAsync(string factoryName, CancellationToken ct)
{
var factory = await factories.GetFirstByNameAsync(factoryName, ct);
return factory?.Enterprise?.Name;
}
}

// 复杂 LINQ 只读查询(入口 OpcenterExDbClient.RunQueryAsync)
public class QueryService(OpcenterExDbClient db)
{
public Task<List<Factory>> ListByEnterpriseAsync(string enterpriseName, CancellationToken ct) =>
db.RunQueryAsync<Factory, List<Factory>>(async (q, token) =>
await q
.Where(f => f.Enterprise != null && f.Enterprise.Name == enterpriseName)
.OrderBy(f => f.Name)
.ToListAsync(token), ct);
}

三、实体类示例

命名空间与 DbSet 以当前代码为准;实体与 IEntityTypeConfiguration 常同文件 partial 声明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
namespace Opcenter.Execution.Data.Entities
{
/// @Description A Factory often represent a physical or logical plant. ...
/// @Source Siemens Opcenter Execution
/// @author lichong
[Table("FACTORY")]
public class Factory : NamedDataObject
{
[Column("CDOTYPEID")]
public new int? CDOTypeId { get; set; }

[Column("CHANGECOUNT")]
public new int? ChangeCount { get; set; }

[Column("DESCRIPTION")]
public new string? Description { get; set; }

[ForeignKey("ENTERPRISEID")]
public virtual Enterprise? Enterprise { get; set; }

[Key]
[Column("FACTORYID")]
public new string? InstanceID { get; set; }

[Column("FACTORYNAME")]
public new string? Name { get; set; }

[Column("NOTES")]
public new string? Notes { get; set; }

[ForeignKey("PRINTQUEUEID")]
public virtual PrintQueue? PrintQueue { get; set; }
}
}

namespace Opcenter.Execution.Data.DbContexts
{
using Opcenter.Execution.Data.Entities;

public partial class OpcenterExDbContext : DbContext
{
public DbSet<Factory> Factories { get; set; }
}

public class FactoryEntityTypeConfiguration : IEntityTypeConfiguration<Factory>
{
public void Configure(EntityTypeBuilder<Factory> builder)
{
}
}
}

四、注意事项

  1. 只读OpcenterExDbContext 在存在 Added/Modified/Deleted 时会拒绝 SaveChanges / SaveChangesAsync;DI 默认 NoTracking
  2. 查询分层:简单按名/条件用 IRepository / INamedDataObjectRepository / IRevisionedObjectRepository;跨实体复杂 LINQ 用 OpcenterExDbClient.RunQueryAsync;原生 SQL 表名经 QualifyTable 限定 schema。
  3. 数据库:SQL Server 与 Oracle 均支持;Oracle 需 Oracle.EntityFrameworkCore
  4. 懒加载:客户端会启用代理懒加载;生产查询更推荐显式 Include / 投影,避免 N+1。

五、版本信息

当前Opcenter Execution版本为2504 Core

项目地址:https://github.com/LicoCode/Opcenter.Execution.Data