Boa noite pessoal, programei por vários anos em VB6 e depois de um tempo sem 
programar estou voltando a ativa com o D2010.
Aprendi rápido o básico como a sintaxe e os componentes, mais estou tendo 
problemas com POO em 3 camadas. Estou fazendo um cadastro simples onde tenho o 
seguinte cenário:

1 DataModule : TSQLConnection, TSQLTable, TSQLStoredProc
1 Form: DataSetprovider, ClientDataSet, DataSource, DBNavigator, os campos das 
tabelas DBEdit, TDBComboBox e os botões de ação incluir, excluir, etc...
1 Unit: que é a minha classe.

Consigo navegar pelos regiostros mais quando tento fazer o cadastro recebo a 
seguinte mensagem: Access violation at address 0060680C in module 
'Cadastro.exe' Write of address 00000004.
Pesquisando percebi que a referência da minha classe está como nil quanto chamo 
o método incluir, mais como carregar a classe corretamente? Me corrijam se eu 
estiver errado.
Segue abaixo o código que estou usando:
A parte em negrito no form é onde acontece o erro. Coloquei um if para tratar o 
erro mais como corrigir?
Desde já agradeço a ajuda de vocês.

DATAMODULE:
unit DMAnoLetivo;

interface

uses
  SysUtils, Classes, DSConnect, DBClient, SConnect, DB, MConnect, WideStrings,
  DBXOracle, SqlExpr, FMTBcd, CLCadAnoLetivo, Dialogs;

type
  TDTMAnoLetivo = class(TDataModule)
    ConnR110ANO: TSQLConnection;
    TableR110ANO: TSQLTable;
    SpR110ANO: TSQLStoredProc;
    TableR110ANOCODANO: TFMTBCDField;
    TableR110ANOANOLET: TFMTBCDField;
    TableR110ANOINIANO: TSQLTimeStampField;
    TableR110ANOFINANO: TSQLTimeStampField;
    TableR110ANOSITANO: TWideStringField;
  private
    { Private declarations }
  public
    { Public declarations }
    function Incluir(FCodAno :TAnoLetivo):Boolean;
  end;

var
  dtmAnoLetivo: TDTMAnoLetivo;

implementation

{$R *.dfm}

{TDTMAnoLetivo}

function TDTMAnoLetivo.Incluir(FCodAno :TAnoLetivo):Boolean;
begin
  result := false;
  try
    if not ConnR110ANO.Connected then
      ConnR110ANO.Open;

    if spR110ANO.Active then
      spR110ANO.Close;

    spR110ANO.ClearFields;

    spR110ANO.StoredProcName := 'spCadAnoLetivo';

    spR110ANO.Params.ParamByName('p_CodAno').Value := FCodAno.CodAno;
    spR110ANO.Params.ParamByName('p_AnoLet').Value := FCodAno.AnoLet;
    spR110ANO.Params.ParamByName('p_IniAno').Value := FCodAno.IniAno;
    spR110ANO.Params.ParamByName('p_FinAno').Value := FCodAno.FinAno;
    spR110ANO.Params.ParamByName('p_SitAno').Value := FCodAno.SitAno;

    spR110ANO.ExecProc;
    result := true;
  except
   on e:exception do
     ShowMessage('Houve um problema de comunicação com o banco de dados!');
  end;
end;

end.

FORM:
unit frmCadAnoLetivoUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, RzBckgnd, RzBorder, ExtCtrls, DBCtrls, Buttons,
  Mask, DB, DBClient, Provider;

type
  TfrmCadAnoLetivo = class(TForm)
    Label2: TLabel;
    Label1: TLabel;
    RzBorder: TRzBorder;
    RzSeparator: TRzSeparator;
    StatusBar: TStatusBar;
    Label3: TLabel;
    Label4: TLabel;
    DBNavigator: TDBNavigator;
    btAlterar: TBitBtn;
    btCancelar: TBitBtn;
    btExcluir: TBitBtn;
    btAjuda: TBitBtn;
    btFechar: TBitBtn;
    btPesquisar: TBitBtn;
    btIncluir: TBitBtn;
    Label5: TLabel;
    cboSituacao: TDBComboBox;
    txtDataFim: TDBEdit;
    txtDataInicio: TDBEdit;
    txtAnoLetivo: TDBEdit;
    cboCodAnoLetivo: TDBComboBox;
    DataSetProvider: TDataSetProvider;
    ClientDataSet: TClientDataSet;
    ClientDataSetCODANO: TFMTBCDField;
    ClientDataSetANOLET: TFMTBCDField;
    ClientDataSetINIANO: TSQLTimeStampField;
    ClientDataSetFINANO: TSQLTimeStampField;
    ClientDataSetSITANO: TWideStringField;
    DataSource: TDataSource;
    tdbAnoLetivo: TDBText;
    procedure btFecharClick(Sender: TObject);
    procedure btIncluirClick(Sender: TObject);
    procedure btCancelarClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure LimparCampos;
    function ValidarCampos :boolean;
  public
    { Public declarations }

  end;

var
  frmCadAnoLetivo: TfrmCadAnoLetivo;

implementation

{$R *.dfm}

uses CLCadAnoLetivo, DMAnoLetivo;

var FAnoLetivo : TAnoLetivo;
{Procedimentos de iniialização e rotinas de limpeza de campos}
procedure TfrmCadAnoLetivo.LimparCampos;
begin
  cboCodAnoLetivo.Clear;
  txtAnoLetivo.Clear;
  txtDataInicio.Clear;
  txtDataFim.Clear;
  cboSituacao.Clear;
end;

{Proedimentos de validação de campo}
function TfrmCadAnoLetivo.ValidarCampos:boolean;
begin
  ValidarCampos := true;

  if txtAnoLetivo.Text = '' then
  begin
    Application.MessageBox('O campo ano letivo não pode estar vazio!', 
'Alerta', MB_ICONEXCLAMATION);
    ValidarCampos := false;
    txtAnoLetivo.SetFocus;
    exit;
  end;

  if txtDataInicio.Text = '' then
  begin
    Application.MessageBox('O campo data inícial não pode estar vazio!', 
'Alerta', MB_ICONEXCLAMATION);
    ValidarCampos := false;
    txtDataInicio.SetFocus;
    exit;
  end;

  if txtDataFim.Text = '' then
  begin
    Application.MessageBox('O campo data final não pode estar vazio!', 
'Alerta', MB_ICONEXCLAMATION);
    ValidarCampos := false;
    txtDataFim.SetFocus;
    exit;
  end;

  if cboSituacao.Text = '' then
  begin
    Application.MessageBox('O campo situação não pode estar vazio!', 'Alerta', 
MB_ICONEXCLAMATION);
    ValidarCampos := false;
    exit;
  end;
end;

procedure TfrmCadAnoLetivo.btCancelarClick(Sender: TObject);
begin
  btIncluir.Caption := '&Incluir';
  btAlterar.Enabled := true;
  btExcluir.Enabled := true;
  cboCodAnoLetivo.Enabled := true;
  DBNavigator.Enabled := true;
end;

procedure TfrmCadAnoLetivo.btFecharClick(Sender: TObject);
begin
  close;
end;

procedure TfrmCadAnoLetivo.btIncluirClick(Sender: TObject);
begin
  if btIncluir.Caption = '&Incluir' then
  begin
    btIncluir.Caption := '&Salvar';
    btAlterar.Enabled := false;
    btExcluir.Enabled := false;
    cboCodAnoLetivo.Enabled := false;
    DBNavigator.Enabled := false;
    cboCodAnoLetivo.Text := '0';
    txtAnoLetivo.Clear;
    txtDataInicio.Clear;
    txtDataFim.Clear;
    cboSituacao.Clear;
    txtAnoLetivo.SetFocus;
  end
  else
  begin
    if not ValidarCampos then exit;

    if FAnoLetivo <> nil then
    begin
      FAnoLetivo.Create;
      FAnoLetivo.CodAno := StrToInt(cboCodAnoLetivo.Text);
      FAnoLetivo.AnoLet := StrToInt(txtAnoLetivo.Text);
      FAnoLetivo.IniAno := txtDataInicio.Text;
      FAnoLetivo.FinAno := txtDataFim.Text;
      FAnoLetivo.SitAno := cboSituacao.Text;
      FAnoLetivo.Incluir;
    end;

    btIncluir.Caption := '&Incluir';
    btAlterar.Enabled := true;
    btExcluir.Enabled := true;
    cboCodAnoLetivo.Enabled := true;
    DBNavigator.Enabled := true;
  end;

end;

procedure TfrmCadAnoLetivo.FormCreate(Sender: TObject);
begin
  LimparCampos;
end;

end.

UNIT:
unit CLCadAnoLetivo;

interface

uses
  Classes, DateUtils, Sysutils;

type
 TAnoLetivo = class

 private
  {Aqui poderia ficar os métodos privados}

  FCodAno :integer;
  FAnoLet :integer;
  FIniAno :string;
  FFinAno :string;
  FSitAno :string;
  FAnoLetivo :TAnoLetivo;

  procedure SetCodAno(CodAno :integer);
  function GetCodAno :integer;

  procedure SetAnoLet(AnoLet :integer);
  function GetAnoLet :integer;

  procedure SetIniAno(IniAno :string);
  function GetIniAno :string;

  procedure SetFinAno(FinAno :string);
  function GetFinAno :string;

  procedure SetSitAno(SitAno :string);
  function GetSitAno :string;

 published

 public
  {Construtores e Destrutores}
  constructor Create;
  destructor Destroy; override;

  {Métodos}
  function Incluir:Boolean;
  function Alterar(CodAno :integer) :boolean;
  function Exluir(CodAno :integer) :boolean;
  procedure CarregarComboAnoLetivo;
  procedure Clear;

  {Propriedades}
  property CodAno :integer read GetCodAno write SetCodAno;
  property AnoLet :integer read GetAnoLet write SetAnoLet;
  property IniAno :string read GetIniAno write SetIniAno;
  property FinAno :string read GetFinAno write SetFinAno;
  property SitAno :string read GetSitAno write SetSitAno;
  property AnoLetivo :TAnoLetivo read FAnoLetivo write FAnoLetivo;
end;

implementation

{TAnoLetivo}

uses DMAnoLetivo;

procedure TAnoLetivo.SetCodAno(CodAno: integer);
begin
  FCodAno := CodAno;
end;

function TAnoLetivo.GetCodAno :integer;
begin
  GetCodAno := FCodAno;
end;

procedure TAnoLetivo.SetAnoLet(AnoLet: integer);
begin
  FAnoLet := AnoLet;
end;

function TAnoLetivo.GetAnoLet :integer;
begin
  GetAnoLet := FAnoLet;
end;

procedure TAnoLetivo.SetIniAno(IniAno: string);
begin
  FIniAno := IniAno;
end;

function TAnoLetivo.GetIniAno :string;
begin
  GetIniAno := FIniAno;
end;

procedure TAnoLetivo.SetFinAno(FinAno: string);
begin
  FFinAno := FinAno;
end;

function TAnoLetivo.GetFinAno :string;
begin
  GetFinAno := FFinAno;
end;

procedure TAnoLetivo.SetSitAno(SitAno: string);
begin
  FSitAno := SitAno;
end;

function TAnoLetivo.GetSitAno :string;
begin
  GetSitAno := FSitAno;
end;

constructor TAnoletivo.Create;
begin
  inherited;
  CodAno := 0;
  AnoLet := 0;
  IniAno := '';
  FinAno := '';
  SitAno := '';
  FAnoLetivo.Clear;
end;

destructor TAnoLetivo.Destroy;
begin
  FAnoLetivo.Free;
  inherited;
end;

function TAnoLetivo.Incluir:Boolean;
begin
  dtmAnoLetivo.Incluir(Self);
end;

function TAnoLetivo.Alterar(CodAno :integer): Boolean;
begin

end;

function TAnoLetivo.Exluir(CodAno :integer): Boolean;
begin

end;

procedure TAnoLetivo.CarregarComboAnoLetivo;
begin

end;

procedure TAnoLetivo.Clear;
begin
  CodAno := 0;
  AnoLet := 0;
  IniAno := '';
  FinAno := '';
  SitAno := '';
end;

end.

[As partes desta mensagem que não continham texto foram removidas]

Responder a