Ecto 与 Elixir 集成:数据库交互入门指南

简介

在我学习 Elixir 的过程中,我发现了 Ecto ,这是一个强大的数据库封装器和查询生成器,能够无缝对接 SQL 数据库。尽管常与 Entity Framework Core 或 Ruby on Rails 的 ActiveRecord 等 ORM 框架对比,但 Ecto 的设计不同:它不自动跟踪状态,要求开发者显式管理数据变化。本文将探讨 Ecto 的核心概念,包括仓库(Repository)、模式(Schema)、迁移(Migration)和基础增删改查(CRUD)操作。高级功能请参考 Ecto 官方文档 

什么是 Ecto?

Ecto 是 Elixir 的数据库封装器和查询生成器,专为 PostgreSQL、MySQL 等关系型数据库设计。它提供以下功能:

  • 映射数据库表到 Elixir 结构体(通过 Schema)
  • 使用 Elixir 语法生成类型安全的查询
  • 通过变更集(Changeset)在持久化前验证数据
  • 通过版本控制的迁移管理数据库模式演进

为什么 Ecto 不是传统 ORM

Ecto 通过以下方式避免传统 ORM 的陷阱:

  1. 无自动状态跟踪 :不同于 ORM,Ecto 不会跟踪实体状态(如脏字段或修改字段)。
  2. 显式数据流 :开发者必须手动通过变更集传递数据后才能持久化。
  3. 函数式编程范式 :Ecto 与 Elixir 的函数式编程模型一致,避免对象-关系映射的“阻抗失配”。

要求

  • Elixir 1.18+ (根据需要调整旧版本)
  • mix.exs 中的依赖:
{:ecto_sql, "~> 3.0"},  # Ecto
{:postgrex, ">= 0.0.0"} # PostgreSQL驱动

设置仓库(Repository)

仓库(或 Repo)是 Ecto 与数据库交互的接口,类似于 Entity FrameworkDbContext

手动设置

1. 定义仓库模块:

defmodule Friends.Repo do
  use Ecto.Repo,
      otp_app: :friend,
      adapter: Ecto.Adapters.Postgres
end

2. 在 config/config.exs 中配置:

config :friends, Friends.Repo,
  database: "friends",
  username: "user",
  password: "pass",
  hostname: "localhost"

通过 Mix 任务自动设置

运行:

mix ecto.gen.repo -r Friends.Repo

启动时运行 Ecto

lib/<app_name>/application.ex 的应用监督者中添加仓库:

def start(_type, _args) do
  children = [Friends.Repo]
  ...
end

然后更新 config/config.exs

config :friends, ecto_repos: [Friends.Repo]

创建模式(Schema)

模式将数据库表映射为 Elixir 结构体。例如,定义一个 Person 模式:

defmodule Friends.Person do
  use Ecto.Schema
  import Ecto.Changeset

  schema "people" do
    field :first_name, :string
    field :last_name, :string
    field :age, :integer
  end

  def changeset(person, params \\ %{}) do
    person
    |> cast(params, [:first_name, :last_name, :age])
    |> validate_required([:first_name, :last_name])
  end
end

迁移(Migration)

迁移以增量方式定义数据库模式变更。

手动迁移

priv/repo/migrations/<datetime>_create_people.exs 创建文件:

defmodule Friends.Repo.Migrations.CreatePeople do
  use Ecto.Migration

  def change do
    create table(:people) do
      add :first_name, :string
      add :last_name, :string
      add :age, :integer
    end
  end
end

通过 Mix 任务自动生成迁移

运行:

mix ecto.gen.migration create_people

该命令会创建一个空迁移文件:

defmodule Friends.Repo.Migrations.CreatePeople do
  use Ecto.Migration

  def change do

  end
end

执行迁移

运行:

mix ecto.create # 创建数据库
mix ecto.migrate # 执行迁移

增删改查(CRUD)操作

创建(Create)

插入新记录:

person = %Friends.Person{first_name: "Alice", last_name: "Smith", age: 30}
{:ok, inserted_person} = Friends.Repo.insert(person)

带验证的插入:

changeset = Friends.Person.changeset(%Friends.Person{}, %{first_name: "Alice"})
case Friends.Repo.insert(changeset) do
  {:ok, person} -> # 成功
  {:error, changeset} -> # 处理错误
end

读取(Read)

获取记录:

# 通过 ID 获取
Friends.Repo.get(Friends.Person, 1)

# 获取第一条记录
Friends.Repo.one(from p in Friends.Person, order_by: [asc: p.id], limit: 1)

# 获取符合条件的所有记录
Friends.Repo.all(from p in Friends.Person, where: like(p.first_name, "A%"))

更新(Update)

更新现有记录:

person = Friends.Repo.get!(Friends.Person, 1)
changeset = Friends.Person.changeset(person, %{age: 31})
Friends.Repo.update(changeset)

删除(Delete)

删除记录:

person = Friends.Repo.get!(Friends.Person, 1)
Friends.Repo.delete(person)

结论

Ecto 在抽象与控制之间取得平衡,提供以下优势:

  • 类型安全的查询 :编译时宏生成的查询可避免运行时错误。
  • 显式工作流 :变更集强制在持久化前验证数据。
  • 社区支持 :在 Elixir 生态系统中广泛采用。

尽管不是传统 ORM,Ecto 的函数式设计避免了常见的对象-关系映射抽象漏洞。对于高级模式(如关联关系),可探索其对 has_manybelongs_tomany_to_many 的支持。

参考

多源动态最优潮流的分布鲁棒优化方法(IEEE118节点)(Matlab代码实现)内容概要:本文介绍了基于Matlab代码实现的多源动态最优潮流的分布鲁棒优化方法,适用于IEEE118节点电力系统。该方法结合两阶段鲁棒模型确定性模型,旨在应对电力系统中多源输入(如可再生能源)的不确定性,提升系统运行的安全性经济性。文中详细阐述了分布鲁棒优化的建模思路,包括不确定性集合的构建、目标函数的设计以及约束条件的处理,并通过Matlab编程实现算法求解,提供了完整的仿真流程结果分析。此外,文档还列举了大量相关电力系统优化研究案例,涵盖微电网调度、电动汽车集群并网、需求响应、储能配置等多个方向,展示了其在实际工程中的广泛应用价值。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事能源系统优化工作的工程师。; 使用场景及目标:①用于研究高比例可再生能源接入背景下电力系统的动态最优潮流问题;②支撑科研工作中对分布鲁棒优化模型的复现改进;③为电力系统调度、规划及运行决策提供理论支持仿真工具。; 阅读建议:建议读者结合提供的Matlab代码IEEE118节点系统参数进行实操演练,深入理解分布鲁棒优化的建模逻辑求解过程,同时可参考文中提及的其他优化案例拓展研究思路。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值