03-快速入门与环境配置

第三章:快速入门与环境配置

3.1 开发环境准备

3.1.1 必要的开发工具

工具 要求 说明
Visual Studio 2019/2022 推荐使用最新版本
.NET SDK 2.0 - 8.0 根据项目目标框架选择
NuGet 内置 包管理工具
SQL Server / MySQL / 其他 任意版本 开发用数据库

3.1.2 .NET版本与NuGet包对应关系

目标框架 NuGet包名 版本
.NET 6.0+ PWMIS.SOD 6.0+
.NET 5/.NET Core/.NET 4.x PDF.NET.SOD 7.0
.NET 2.0 - 4.x PDF.NET.SOD 6.x及以下

3.1.3 数据库支持

SOD框架内置支持以下数据库:

数据库 内置/扩展 providerName
SQL Server 内置 SqlServer
Access 内置 Access
Oracle 内置 Oracle
SQL CE 内置 SqlCe
OleDb 内置 OleDb
ODBC 内置 Odbc

扩展支持的数据库:

数据库 NuGet包 providerName
MySQL PDF.NET.SOD.MySQL.Provider PWMIS.DataProvider.Data.MySQL,PWMIS.MySqlClient
PostgreSQL PDF.NET.SOD.PostgreSQL.Provider PWMIS.DataProvider.Data.PostgreSQL,PWMIS.PostgreSQLClient
SQLite PDF.NET.SOD.SQLite.Provider PWMIS.DataProvider.Data.SQLite,PWMIS.SQLiteClient
达梦 PWMIS.SOD.DaMeng.Provider PWMIS.DataProvider.Data.Dameng,PWMIS.DamengClient
人大金仓 PWMIS.SOD.Kingbase.Provider PWMIS.DataProvider.Data.Kingbase,PWMIS.KingbaseClient

3.2 创建第一个SOD项目

3.2.1 创建控制台项目

使用Visual Studio:

  1. 打开Visual Studio
  2. 选择"创建新项目"
  3. 选择"控制台应用"模板
  4. 设置项目名称,如:SODDemo
  5. 选择目标框架(推荐.NET 6.0或更高版本)

使用命令行:

# 创建.NET 6.0控制台项目
dotnet new console -n SODDemo -f net6.0

# 进入项目目录
cd SODDemo

3.2.2 安装NuGet包

使用包管理器控制台:

# .NET 6.0及以上版本
Install-Package PWMIS.SOD

# .NET 5及以下版本
Install-Package PDF.NET.SOD

使用命令行:

# .NET 6.0及以上版本
dotnet add package PWMIS.SOD

# .NET 5及以下版本
dotnet add package PDF.NET.SOD

使用NuGet包管理器界面:

  1. 右键项目 → "管理NuGet程序包"
  2. 搜索"PWMIS.SOD"或"PDF.NET.SOD"
  3. 安装最新版本

3.2.3 配置数据库连接

在项目中创建或编辑appsettings.json(.NET Core/5+)或app.config(.NET Framework):

.NET Core/5+项目(appsettings.json):

{
  "ConnectionStrings": {
    "Default": "Server=.;Database=SODDemo;Trusted_Connection=True;TrustServerCertificate=True"
  }
}

然后在代码中配置:

// 设置连接字符串
MyDB.Instance.ConnectionString = "Server=.;Database=SODDemo;...";
MyDB.Instance.DataProvider = new SqlServer();

.NET Framework项目(app.config):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="local" 
         connectionString="Data Source=.;Initial Catalog=SODDemo;Integrated Security=True" 
         providerName="SqlServer"/>
  </connectionStrings>
</configuration>

3.2.4 定义第一个实体类

创建User.cs文件:

using PWMIS.DataMap.Entity;

namespace SODDemo
{
    // 方式1:定义接口类型(用于动态创建实体类)
    public interface IUser
    {
        int ID { get; set; }
        string Name { get; set; }
        string Email { get; set; }
        DateTime CreateTime { get; set; }
    }

    // 方式2:定义完整的实体类
    public class UserEntity : EntityBase
    {
        public UserEntity()
        {
            TableName = "TbUser";        // 映射的表名
            IdentityName = "ID";         // 自增字段名
            PrimaryKeys.Add("ID");       // 主键字段
        }

        public int ID
        {
            get { return getProperty<int>("ID"); }
            set { setProperty("ID", value); }
        }

        public string Name
        {
            get { return getProperty<string>("Name"); }
            set { setProperty("Name", value, 50); }  // 字段长度50
        }

        public string Email
        {
            get { return getProperty<string>("Email"); }
            set { setProperty("Email", value, 100); }
        }

        public DateTime CreateTime
        {
            get { return getProperty<DateTime>("CreateTime"); }
            set { setProperty("CreateTime", value); }
        }
    }
}

3.2.5 创建数据上下文(可选)

如果需要使用Code First自动创建表:

using PWMIS.DataMap.Entity;

namespace SODDemo
{
    public class DemoDbContext : DbContext
    {
        public DemoDbContext() : base("local")  // 使用配置名"local"
        {
        }

        protected override bool CheckAllTableExists()
        {
            // 检查并创建用户表
            CheckTableExists<UserEntity>();
            return true;
        }
    }
}

3.2.6 编写第一个程序

using System;
using PWMIS.DataProvider.Data;
using PWMIS.DataMap.Entity;
using PWMIS.Core;

namespace SODDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("=== SOD框架快速入门示例 ===\n");

            // 1. 初始化数据上下文(自动创建表)
            var context = new DemoDbContext();
            Console.WriteLine("数据库初始化完成!\n");

            // 2. 创建用户数据
            var user = new UserEntity
            {
                Name = "张三",
                Email = "zhangsan@example.com",
                CreateTime = DateTime.Now
            };

            // 3. 插入数据
            int insertResult = context.Add(user);
            if (insertResult > 0)
            {
                Console.WriteLine($"插入成功!用户ID: {user.ID}");
            }

            // 4. 查询数据(使用OQL)
            var queryUser = new UserEntity();
            queryUser.Name = "张三";
            
            var oql = OQL.From(queryUser)
                .Select()
                .Where(queryUser.Name)
                .END;
            
            var users = EntityQuery<UserEntity>.QueryList(oql);
            Console.WriteLine($"\n查询到 {users.Count} 条记录:");
            foreach (var u in users)
            {
                Console.WriteLine($"  ID={u.ID}, Name={u.Name}, Email={u.Email}");
            }

            // 5. 更新数据
            user.Email = "zhangsan_new@example.com";
            int updateResult = context.Update(user);
            Console.WriteLine($"\n更新结果:{updateResult} 行受影响");

            // 6. 删除数据
            int deleteResult = context.Remove(user);
            Console.WriteLine($"删除结果:{deleteResult} 行受影响");

            Console.WriteLine("\n=== 示例运行完成 ===");
            Console.ReadKey();
        }
    }
}

3.3 使用AdoHelper直接操作数据库

3.3.1 创建AdoHelper实例

using PWMIS.DataProvider.Data;

// 方式1:从配置文件读取
AdoHelper db = MyDB.GetDBHelperByConnectionName("local");

// 方式2:读取最后一个配置
AdoHelper db = MyDB.GetDBHelper();

// 方式3:直接创建
AdoHelper db = new SqlServer();
db.ConnectionString = "Data Source=.;Initial Catalog=SODDemo;Integrated Security=True";

3.3.2 执行SQL语句

AdoHelper db = MyDB.GetDBHelper();

// 创建表
string createTableSql = @"
CREATE TABLE TbUser (
    ID INT IDENTITY(1,1) PRIMARY KEY,
    Name NVARCHAR(50),
    Email NVARCHAR(100),
    CreateTime DATETIME
)";

try
{
    db.ExecuteNonQuery(createTableSql);
    Console.WriteLine("表创建成功!");
}
catch (Exception ex)
{
    Console.WriteLine($"表已存在或创建失败:{ex.Message}");
}

// 插入数据(参数化查询)
string insertSql = "INSERT INTO TbUser (Name, Email, CreateTime) VALUES (@Name, @Email, @CreateTime)";
var parameters = new IDataParameter[]
{
    db.GetParameter("@Name", "张三"),
    db.GetParameter("@Email", "zhangsan@example.com"),
    db.GetParameter("@CreateTime", DateTime.Now)
};

int rows = db.ExecuteNonQuery(insertSql, CommandType.Text, parameters);
Console.WriteLine($"插入 {rows} 行");

// 查询数据
string selectSql = "SELECT * FROM TbUser WHERE Name = @Name";
var queryParams = new IDataParameter[]
{
    db.GetParameter("@Name", "张三")
};

DataSet ds = db.ExecuteDataSet(selectSql, CommandType.Text, queryParams);
DataTable dt = ds.Tables[0];

foreach (DataRow row in dt.Rows)
{
    Console.WriteLine($"ID={row["ID"]}, Name={row["Name"]}");
}

3.3.3 微型ORM查询

// 使用占位符参数的简化查询
string sql = "SELECT ID, Name, Email FROM TbUser WHERE Name = {0}";

// 方式1:映射到匿名类型
var users = db.ExecuteMapper(sql, "张三")
    .MapToList(reader => new
    {
        ID = reader.GetInt32(0),
        Name = reader.GetString(1),
        Email = reader.GetString(2)
    });

// 方式2:映射到POCO类
var userList = db.QueryList<UserInfo>(sql, "张三");

// UserInfo是一个简单的POCO类
public class UserInfo
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

3.4 使用ORM进行CRUD操作

3.4.1 创建实体类对象

// 方式1:直接创建实体类实例
UserEntity user = new UserEntity();
user.Name = "张三";
user.Email = "zhangsan@example.com";
user.CreateTime = DateTime.Now;

// 方式2:使用接口动态创建
IUser iUser = EntityBuilder.CreateEntity<IUser>();
iUser.Name = "李四";
iUser.Email = "lisi@example.com";

3.4.2 插入数据

AdoHelper db = MyDB.GetDBHelper();
UserEntity user = new UserEntity
{
    Name = "张三",
    Email = "zhangsan@example.com",
    CreateTime = DateTime.Now
};

// 方式1:使用EntityQuery
int result = EntityQuery<UserEntity>.Instance.Insert(user, db);
Console.WriteLine($"插入成功,自增ID: {user.ID}");

// 方式2:使用DbContext
var context = new DemoDbContext();
context.Add(user);

3.4.3 查询数据

// 查询单个对象
UserEntity queryUser = new UserEntity();
queryUser.ID = 1;

var oql = OQL.From(queryUser)
    .Select()
    .Where(queryUser.ID)
    .END;

UserEntity result = EntityQuery<UserEntity>.QueryObject(oql);

// 查询列表
UserEntity listQuery = new UserEntity();
listQuery.Name = "张";  // 模糊匹配

var listOql = OQL.From(listQuery)
    .Select()
    .Where(cmp => cmp.Comparer(listQuery.Name, "like", "张%"))
    .OrderBy(order => order.Desc(listQuery.ID))
    .END;

List<UserEntity> users = EntityQuery<UserEntity>.QueryList(listOql);

3.4.4 更新数据

UserEntity user = new UserEntity();
user.ID = 1;  // 主键

// 先查询
var oql = OQL.From(user).Select().Where(user.ID).END;
UserEntity existUser = EntityQuery<UserEntity>.QueryObject(oql);

// 修改属性
existUser.Email = "new_email@example.com";

// 更新(只更新修改过的字段)
int result = EntityQuery<UserEntity>.Instance.Update(existUser, db);

// 批量更新
UserEntity updateUser = new UserEntity();
updateUser.Email = "batch@example.com";  // 要更新的值

var batchOql = OQL.From(updateUser)
    .Update(updateUser.Email)
    .Where(cmp => cmp.Comparer(updateUser.Name, "like", "张%"))
    .END;

int affected = EntityQuery<UserEntity>.ExecuteOql(batchOql, db);

3.4.5 删除数据

UserEntity user = new UserEntity();
user.ID = 1;

// 方式1:根据主键删除
int result = EntityQuery<UserEntity>.Instance.Delete(user, db);

// 方式2:使用OQL条件删除
var deleteOql = OQL.From(user)
    .Delete()
    .Where(cmp => cmp.Property(user.Name) == "张三")
    .END;

int affected = EntityQuery<UserEntity>.ExecuteOql(deleteOql, db);

// 方式3:使用DbContext
var context = new DemoDbContext();
context.Remove(user);

3.5 使用GOQL简化查询

GOQL(Generic OQL)是OQL的泛型版本,更加简洁:

using PWMIS.Core.Extensions;

// 简单查询
var users = OQL.FromObject<UserEntity>()
    .Select()
    .Where((cmp, u) => cmp.Property(u.Name) == "张三")
    .END
    .ToList();

// 带条件和排序的查询
var pageUsers = OQL.FromObject<UserEntity>()
    .Select(s => new object[] { s.ID, s.Name, s.Email })
    .Where((cmp, u) => cmp.Property(u.CreateTime) >= DateTime.Today)
    .OrderBy((order, u) => order.Desc(u.ID))
    .Limit(10, 1)  // 分页
    .ToList();

// 使用接口类型查询
var iUsers = OQL.FromObject<IUser>()
    .Select()
    .Where((cmp, u) => cmp.Comparer(u.Name, "like", "张%"))
    .ToList();

3.6 完整示例项目

3.6.1 项目结构

SODDemo/
├── Program.cs                 # 主程序
├── Entities/
│   ├── UserEntity.cs         # 用户实体
│   └── OrderEntity.cs        # 订单实体
├── DataAccess/
│   └── DemoDbContext.cs      # 数据上下文
├── Services/
│   └── UserService.cs        # 业务逻辑层
├── app.config                # 配置文件
└── SODDemo.csproj            # 项目文件

3.6.2 完整代码示例

UserEntity.cs:

using PWMIS.DataMap.Entity;
using System;

namespace SODDemo.Entities
{
    public class UserEntity : EntityBase
    {
        public UserEntity()
        {
            TableName = "TbUser";
            IdentityName = "ID";
            PrimaryKeys.Add("ID");
        }

        public int ID
        {
            get { return getProperty<int>("ID"); }
            set { setProperty("ID", value); }
        }

        public string Name
        {
            get { return getProperty<string>("Name"); }
            set { setProperty("Name", value, 50); }
        }

        public string Email
        {
            get { return getProperty<string>("Email"); }
            set { setProperty("Email", value, 100); }
        }

        public int Status
        {
            get { return getProperty<int>("Status"); }
            set { setProperty("Status", value); }
        }

        public DateTime CreateTime
        {
            get { return getProperty<DateTime>("CreateTime"); }
            set { setProperty("CreateTime", value); }
        }
    }
}

DemoDbContext.cs:

using PWMIS.DataMap.Entity;
using SODDemo.Entities;

namespace SODDemo.DataAccess
{
    public class DemoDbContext : DbContext
    {
        public DemoDbContext() : base("local")
        {
        }

        protected override bool CheckAllTableExists()
        {
            CheckTableExists<UserEntity>();
            return true;
        }
    }
}

UserService.cs:

using System;
using System.Collections.Generic;
using PWMIS.DataProvider.Data;
using PWMIS.DataMap.Entity;
using SODDemo.Entities;

namespace SODDemo.Services
{
    public class UserService
    {
        private readonly AdoHelper _db;

        public UserService()
        {
            _db = MyDB.GetDBHelper();
        }

        // 添加用户
        public int AddUser(string name, string email)
        {
            var user = new UserEntity
            {
                Name = name,
                Email = email,
                Status = 1,
                CreateTime = DateTime.Now
            };

            EntityQuery<UserEntity>.Instance.Insert(user, _db);
            return user.ID;
        }

        // 根据ID获取用户
        public UserEntity GetUser(int id)
        {
            var user = new UserEntity { ID = id };
            var oql = OQL.From(user).Select().Where(user.ID).END;
            return EntityQuery<UserEntity>.QueryObject(oql, _db);
        }

        // 获取所有用户
        public List<UserEntity> GetAllUsers()
        {
            var user = new UserEntity();
            var oql = OQL.From(user)
                .Select()
                .Where(cmp => cmp.Property(user.Status) == 1)
                .OrderBy(order => order.Desc(user.ID))
                .END;
            return EntityQuery<UserEntity>.QueryList(oql, _db);
        }

        // 更新用户邮箱
        public bool UpdateEmail(int id, string newEmail)
        {
            var user = GetUser(id);
            if (user == null) return false;

            user.Email = newEmail;
            return EntityQuery<UserEntity>.Instance.Update(user, _db) > 0;
        }

        // 删除用户
        public bool DeleteUser(int id)
        {
            var user = new UserEntity { ID = id };
            return EntityQuery<UserEntity>.Instance.Delete(user, _db) > 0;
        }

        // 分页查询
        public List<UserEntity> GetUsersByPage(int pageIndex, int pageSize, out int totalCount)
        {
            var user = new UserEntity();
            var oql = OQL.From(user)
                .Select()
                .Where(cmp => cmp.Property(user.Status) == 1)
                .OrderBy(order => order.Desc(user.ID))
                .END;

            oql.Limit(pageSize, pageIndex, true);  // true表示同时计算总数
            
            var list = EntityQuery<UserEntity>.QueryList(oql, _db);
            totalCount = oql.PageWithAllRecordCount;
            
            return list;
        }
    }
}

Program.cs:

using System;
using SODDemo.DataAccess;
using SODDemo.Services;

namespace SODDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("=== SOD框架完整示例 ===\n");

            // 初始化数据库
            var context = new DemoDbContext();
            Console.WriteLine("数据库初始化完成!\n");

            // 创建服务
            var userService = new UserService();

            // 1. 添加用户
            Console.WriteLine("--- 添加用户 ---");
            int id1 = userService.AddUser("张三", "zhangsan@example.com");
            int id2 = userService.AddUser("李四", "lisi@example.com");
            int id3 = userService.AddUser("王五", "wangwu@example.com");
            Console.WriteLine($"添加了3个用户,ID分别为: {id1}, {id2}, {id3}\n");

            // 2. 查询单个用户
            Console.WriteLine("--- 查询用户 ---");
            var user = userService.GetUser(id1);
            Console.WriteLine($"查询到用户: ID={user.ID}, Name={user.Name}, Email={user.Email}\n");

            // 3. 查询所有用户
            Console.WriteLine("--- 所有用户列表 ---");
            var allUsers = userService.GetAllUsers();
            foreach (var u in allUsers)
            {
                Console.WriteLine($"  ID={u.ID}, Name={u.Name}, Email={u.Email}");
            }
            Console.WriteLine();

            // 4. 更新用户
            Console.WriteLine("--- 更新用户邮箱 ---");
            bool updated = userService.UpdateEmail(id1, "zhangsan_new@example.com");
            Console.WriteLine($"更新结果: {(updated ? "成功" : "失败")}\n");

            // 5. 分页查询
            Console.WriteLine("--- 分页查询 ---");
            var pageUsers = userService.GetUsersByPage(1, 2, out int totalCount);
            Console.WriteLine($"总记录数: {totalCount}, 当前页记录数: {pageUsers.Count}");
            foreach (var u in pageUsers)
            {
                Console.WriteLine($"  ID={u.ID}, Name={u.Name}");
            }
            Console.WriteLine();

            // 6. 删除用户
            Console.WriteLine("--- 删除用户 ---");
            bool deleted = userService.DeleteUser(id3);
            Console.WriteLine($"删除用户 {id3} 结果: {(deleted ? "成功" : "失败")}\n");

            Console.WriteLine("=== 示例运行完成 ===");
            Console.ReadKey();
        }
    }
}

3.7 常见问题与解决方案

3.7.1 连接字符串配置问题

问题:找不到连接配置

解决:确保app.config或appsettings.json配置正确,并且配置文件已复制到输出目录。

<!-- app.config 需要在配置正确的节点下 -->
<configuration>
  <connectionStrings>
    <add name="local" connectionString="..." providerName="SqlServer"/>
  </connectionStrings>
</configuration>

3.7.2 数据库提供程序问题

问题:无法加载数据库提供程序

解决

  1. 安装对应的NuGet包
  2. 确保providerName格式正确
<!-- 扩展提供程序的格式 -->
<add name="mysql" 
     connectionString="Server=localhost;Database=test;Uid=root;Pwd=123456;" 
     providerName="PWMIS.DataProvider.Data.MySQL,PWMIS.MySqlClient"/>

3.7.3 实体类映射问题

问题:查询结果为空或字段值为null

解决

  1. 检查TableName是否正确
  2. 检查属性名与字段名是否匹配
  3. 确认getProperty/setProperty中的字段名
// 检查映射配置
public class UserEntity : EntityBase
{
    public UserEntity()
    {
        TableName = "TbUser";  // 确保表名正确
    }
    
    public string Name
    {
        get { return getProperty<string>("Name"); }  // 确保字段名正确
        set { setProperty("Name", value, 50); }
    }
}

3.7.4 自增ID未回填

问题:插入后实体类的ID属性为0

解决:确保设置了IdentityName

public UserEntity()
{
    TableName = "TbUser";
    IdentityName = "ID";      // 必须设置自增字段名
    PrimaryKeys.Add("ID");    // 添加主键
}

3.8 本章小结

本章介绍了SOD框架的快速入门内容:

  1. 开发环境准备:安装必要的工具和NuGet包
  2. 创建项目:使用VS或命令行创建项目
  3. 配置连接:配置数据库连接字符串
  4. 定义实体类:创建继承EntityBase的实体类
  5. CRUD操作:使用EntityQuery和OQL进行数据操作
  6. GOQL简化:使用泛型OQL简化代码

通过本章的学习,你应该能够使用SOD框架完成基本的数据库操作。在接下来的章节中,我们将深入学习实体类映射、OQL查询语言等高级特性。


下一章预告:第四章将深入讲解SOD实体类的定义、元数据映射机制以及高级映射技巧。

posted @ 2025-11-29 13:40  我才是银古  阅读(2)  评论(0)    收藏  举报