수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1695088
  • Today | 14
  • Yesterday | 819

1 Articles, Search for '데이타 바인딩'

  1. 2007/01/09 ADO 데이타 바인딩 다이얼로그 얻기
Programming/Database Programming2007/01/09 09:01

ADO 데이타 바인딩 다이얼로그 얻기

ADO 데이타 바인딩 다이얼로그 얻기

조경민 오전 10:24 2001-12-24 bro@shinbiro.com

[ADO 데이타 바인딩 다이얼로그 얻기]


VC++에서 ADO를 이용해서 데이타베이스 간단한 레코드 폼을 얻고 싶을떄 다음처럼 하면 기본적인 코드가 자동으로 완성된다.

Project / Add to Project 한 후 Components and Controls에서

Visual C++ Components 안에 ADO Data Bound Dialog를 선택한다.

사용자 삽입 이미지

원하는 DB 연결을 바인드 위자드에서 선택하면 CRsCgDlg 라는 클래스가 생긴다. 바로 DoModal 시키면 레코드 폼이 나온다.

데이타필드가 에디트컨트롤로 자동으로 부여되고, 데이타 네비게이터 버튼도 있다.

다음은 RsCgDlg를 쓴 간단한 예제이다.

(추가/삭제/수정 및 네비게이션, 검색에 대한 코드를 넣었다. 쓸때 참고하면 좋겠다. )

// RsCgDlg.cpp : implementation file

//

#include "stdafx.h"

#include "Common.h"

#include "RsCgDlg.h"

#include "VirusRecordDlg.h"

#include "DBLogic.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CRsCgDlg dialog

#define WM_SEARCH               (WM_USER+100)

CRsCgDlg::CRsCgDlg(CWnd* pParent /*=NULL*/)

   : CDialog(CRsCgDlg::IDD, pParent)

{

   

   m_strConnection.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s\\scanx.mdb;Persist Security Info=False",

       fnBroGetDir());

   m_strCmdText = _T("VIRUS");

   m_pRs = NULL;

   

   //{{AFX_DATA_INIT(CRsCgDlg)

   m_lDlgiD = 0;

   m_strDlgNAME = _T("");

   m_strDlgFNAME = _T("");

   m_lDlgSIZE = 0;

   //m_strDlgBIN = _T("");

   m_strDlgINFO = _T("");

   m_strDlgTREAT = _T("");

   m_nRec = 0;

   m_nTotRec = 0;

   //}}AFX_DATA_INIT

}

CRsCgDlg::~CRsCgDlg()

{

   m_pRs = NULL;

}

BOOL CRsCgDlg::OnInitDialog()

{

   CDialog::OnInitDialog();

   // 기본으로 전체를 얻어온다.

   Open( m_strCmdText );

   return TRUE;

}

void CRsCgDlg::RefreshBoundData()

{

   if (adFldOK == liDStatus)

       m_lDlgiD = m_liD;

   else

       m_lDlgiD = 0;

   if (adFldOK == lNAMEStatus)

       m_strDlgNAME = m_wszNAME;

   else

       m_strDlgNAME = _T("");

   if (adFldOK == lFNAMEStatus)

       m_strDlgFNAME = m_wszFNAME;

   else

       m_strDlgFNAME = _T("");

   if (adFldOK == lSIZEStatus)

       m_lDlgSIZE = m_lSIZE;

   else

       m_lDlgSIZE = 0;

   //if (adFldOK == lBINStatus)

   //  m_strDlgBIN = m_wszBIN[0];

   //else

   //  m_strDlgBIN = _T("");

   if (adFldOK == lINFOStatus)

       m_strDlgINFO = m_wszINFO;

   else

       m_strDlgINFO = _T("");

   if (adFldOK == lTREATStatus)

   {

       switch( m_wszTREAT[0] )

       {

       case SCANX_TREAT_IGNORE :

           m_strDlgTREAT = _T("무시/로그");

           break;

       case SCANX_TREAT_ALERT :

           m_strDlgTREAT = _T("알림/선택");

           break;

       case SCANX_TREAT_TERMINATE :

           m_strDlgTREAT = _T("강제종료");

           break;

       case SCANX_TREAT_DELETE :

           m_strDlgTREAT = _T("종료/삭제");

           break;

       }

       //m_strDlgTREAT = m_wszTREAT;

   }

   else

       m_strDlgTREAT = _T("");

   UpdateData(FALSE);

}

void CRsCgDlg::GenerateError(HRESULT hr, PWSTR pwszDescription)

{

   CString strError;

   strError.Format("Run-time error '%d (%x)'", hr, hr);

   strError += "\n\n";

   strError += pwszDescription;

   AfxMessageBox(strError);

}

void CRsCgDlg::DoDataExchange(CDataExchange* pDX)

{

   CDialog::DoDataExchange(pDX);

   //{{AFX_DATA_MAP(CRsCgDlg)

   DDX_Control(pDX, IDC_EDIT_SEARCH_NAME, m_edtSearchName);

   DDX_Text(pDX, IDC_NAME, m_strDlgNAME);

   DDX_Text(pDX, IDC_FNAME, m_strDlgFNAME);

   DDX_Text(pDX, IDC_FSIZE, m_lDlgSIZE);

   //DDX_Text(pDX, IDC_BIN, m_strDlgBIN);

   DDX_Text(pDX, IDC_INFO, m_strDlgINFO);

   DDX_Text(pDX, IDC_TREAT, m_strDlgTREAT);

   DDX_Text(pDX, IDC_STATIC_REC, m_nRec);

   DDX_Text(pDX, IDC_STATIC_TOTREC, m_nTotRec);

   //}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CRsCgDlg, CDialog)

   //{{AFX_MSG_MAP(CRsCgDlg)

   ON_BN_CLICKED(IDC_MOVEFIRST, OnMovefirst)

   ON_BN_CLICKED(IDC_MOVELAST, OnMovelast)

   ON_BN_CLICKED(IDC_MOVENEXT, OnMovenext)

   ON_BN_CLICKED(IDC_MOVEPREV, OnMoveprev)

   ON_BN_CLICKED(IDC_SEARCHNAME, OnSearchname)

   ON_BN_CLICKED(IDC_ADD, OnAdd)

   ON_BN_CLICKED(IDC_CLOSE, OnClose)

   ON_BN_CLICKED(IDC_DEL, OnDel)

   ON_BN_CLICKED(IDC_EDIT, OnEdit)

   //}}AFX_MSG_MAP

   ON_MESSAGE( WM_SEARCH, OnSearch )

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CRsCgDlg message handlers

void CRsCgDlg::OnMovefirst()

{

   try

   {

       // 처음으로 돌아간다.

       m_pRs->MoveFirst();

       m_nRec = 1;

       // 화면갱신

       RefreshBoundData();

       // 네비게이터 버튼 활성화 조정

       GetDlgItem(IDC_MOVEFIRST)->EnableWindow(FALSE);

       GetDlgItem(IDC_MOVEPREV)->EnableWindow(FALSE);

       GetDlgItem(IDC_MOVELAST)->EnableWindow(TRUE);

       GetDlgItem(IDC_MOVENEXT)->EnableWindow(TRUE);

   }

   catch (_com_error &e)

   {

       GenerateError(e.Error(), e.Description());

   }

}

void CRsCgDlg::OnMovelast()

{

   try

   {

       m_pRs->MoveLast();

       m_nRec = m_nTotRec;

       // 화면갱신

       RefreshBoundData();

       // 네비게이터 버튼 활성화 조정

       GetDlgItem(IDC_MOVELAST)->EnableWindow(FALSE);

       GetDlgItem(IDC_MOVENEXT)->EnableWindow(FALSE);

       GetDlgItem(IDC_MOVEFIRST)->EnableWindow(TRUE);

       GetDlgItem(IDC_MOVEPREV)->EnableWindow(TRUE);

   }

   catch (_com_error &e)

   {

       GenerateError(e.Error(), e.Description());

   }

}

void CRsCgDlg::OnMovenext()

{

   try

   {

       m_pRs->MoveNext();

       m_nRec++;

       // 화면갱신

       RefreshBoundData();

       // 네비게이터 버튼 활성화 조정

       m_pRs->MoveNext();

       if( m_pRs->EndOfFile )

       {

           GetDlgItem(IDC_MOVELAST)->EnableWindow(FALSE);

           GetDlgItem(IDC_MOVENEXT)->EnableWindow(FALSE);

       }

       m_pRs->MovePrevious();

       GetDlgItem(IDC_MOVEFIRST)->EnableWindow(TRUE);

       GetDlgItem(IDC_MOVEPREV)->EnableWindow(TRUE);

   }

   catch (_com_error &e)

   {

       GenerateError(e.Error(), e.Description());

   }

}

void CRsCgDlg::OnMoveprev()

{

   try

   {

       m_pRs->MovePrevious();

       m_nRec--;

       // 화면갱신

       RefreshBoundData();

       // 네비게이터 버튼 활성화 조정

       m_pRs->MovePrevious();

       if( m_pRs->BOF )

       {

           GetDlgItem(IDC_MOVEFIRST)->EnableWindow(FALSE);

           GetDlgItem(IDC_MOVEPREV)->EnableWindow(FALSE);

       }

       m_pRs->MoveNext();

       GetDlgItem(IDC_MOVELAST)->EnableWindow(TRUE);

       GetDlgItem(IDC_MOVENEXT)->EnableWindow(TRUE);

   }

   catch (_com_error &e)

   {

       GenerateError(e.Error(), e.Description());

   }

}

void CRsCgDlg::Open( LPCTSTR lpszSQL )

{

   HRESULT hr = NOERROR;

   IADORecordBinding *piAdoRecordBinding = NULL;

   try

   {

       m_nRec = 0;

       m_pRs = NULL;

       m_pRs.CreateInstance(__uuidof(Recordset));

       m_pRs->CursorLocation = adUseClient;

       m_pRs->Open((LPCTSTR)lpszSQL, (LPCTSTR)m_strConnection, adOpenStatic,

           adLockBatchOptimistic, adCmdTableDirect);

       if (FAILED(hr = m_pRs->QueryInterface(__uuidof(IADORecordBinding), (LPVOID *)&piAdoRecordBinding)))

           _com_issue_error(hr);

       if (FAILED(hr = piAdoRecordBinding->BindToRecordset(this)))

           _com_issue_error(hr);

       if( m_pRs->EndOfFile && m_pRs->BOF)

       {

           m_nTotRec = 0;

       }

       else

       {

           m_pRs->MoveLast();

           m_pRs->MoveFirst();

           m_nTotRec = m_pRs->GetRecordCount();

           m_nRec = 1;

       }

       // 추가 삭제 수정 버튼 Enable 할것인지 결정

       BOOL bEnableOpt = TRUE;

       if( m_nTotRec == 0 )

       {

           bEnableOpt = FALSE;

           m_strDlgNAME = _T("");

           m_strDlgFNAME = _T("");

           m_lDlgSIZE = 0;

           m_strDlgINFO = _T("");

           m_strDlgTREAT = _T("");

       }

       GetDlgItem(IDC_ADD)->EnableWindow(bEnableOpt);

       GetDlgItem(IDC_DEL)->EnableWindow(bEnableOpt);

       GetDlgItem(IDC_EDIT)->EnableWindow(bEnableOpt);

       if( m_nTotRec < 2)

       {

           // 레코드가 없거나 하나다

           GetDlgItem(IDC_MOVEFIRST)->EnableWindow(FALSE);

           GetDlgItem(IDC_MOVEPREV)->EnableWindow(FALSE);

           GetDlgItem(IDC_MOVENEXT)->EnableWindow(FALSE);

           GetDlgItem(IDC_MOVELAST)->EnableWindow(FALSE);

       }

       else

       {

           // 레코드가 있다.

           GetDlgItem(IDC_MOVEFIRST)->EnableWindow(FALSE);

           GetDlgItem(IDC_MOVEPREV)->EnableWindow(FALSE);

           GetDlgItem(IDC_MOVENEXT)->EnableWindow(TRUE);

           GetDlgItem(IDC_MOVELAST)->EnableWindow(TRUE);

       }

       if( m_nTotRec != 0 )

           RefreshBoundData();

       else

           UpdateData(FALSE);

   }

   catch (_com_error &e)

   {

       GenerateError(e.Error(), e.Description());

   }

   if (piAdoRecordBinding)

       piAdoRecordBinding->Release();  

}

LRESULT CRsCgDlg::OnSearch( WPARAM wparam, LPARAM lparam )

{

   CString sSearchName;

   m_edtSearchName.GetWindowText(sSearchName);

   CString sSQL;

   // 원하는 SQL문을 만들어낸다.

   sSQL.Format("SELECT * FROM VIRUS WHERE NAME like '%s", sSearchName );

   sSQL+="%'";

   

   Open(sSQL);

   CString sMsg;

   sMsg.Format("총 %lu개의 레코드가 검색되었습니다.", m_nTotRec );

   MessageBox( sMsg, "검색 완료" );

   return 1;

}

BOOL CRsCgDlg::PreTranslateMessage(MSG* pMsg)

{

   // TODO: Add your specialized code here and/or call the base class

   if( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN )

   {

       if( GetFocus() == &m_edtSearchName )

           PostMessage( WM_SEARCH );

   }

   return CDialog::PreTranslateMessage(pMsg);

}

void CRsCgDlg::OnSearchname()

{

   // TODO: Add your control notification handler code here

   PostMessage( WM_SEARCH );

}

void CRsCgDlg::OnAdd()

{

   // TODO: Add your control notification handler code here

   CVirusRecordDlg dlg;

   // 추가창 모드로 연다.

   dlg.m_nMode = MODE_INSERT;

   if( dlg.DoModal() == IDOK )

   {

       CString sBin,sFName;

       if( !CDBLogic::GetBin( dlg.m_sFilePath , &sBin) )

           return;

       try

       {

           m_pRs->AddNew();

           m_pRs->Fields->GetItem("NAME")->put_Value( _variant_t(dlg.m_sName) );

           m_pRs->Fields->GetItem("FNAME")->put_Value( _variant_t(dlg.m_sFileName) );

           m_pRs->Fields->GetItem("SIZE")->put_Value( _variant_t(dlg.m_sSize) );

           m_pRs->Fields->GetItem("BIN")->put_Value( _variant_t(sBin) );

           m_pRs->Fields->GetItem("INFO")->put_Value( _variant_t(dlg.m_sInfo) );

           m_pRs->Fields->GetItem("TREAT")->put_Value( _variant_t(CString(dlg.m_sTreat[0])) );

           m_pRs->Update();

           //m_pRs->Requery(adCmdTable);

           m_pRs->UpdateBatch(adAffectCurrent);

           //RefreshBoundData();  

       }

       catch (_com_error &e)

       {

           GenerateError(e.Error(), e.Description());

       }      

       Open( _T("VIRUS"));

   }

}

void CRsCgDlg::OnClose()

{

   // TODO: Add your control notification handler code here

   EndDialog(IDOK);

}

void CRsCgDlg::OnDel()

{

   // TODO: Add your control notification handler code here

   try

   {

       m_pRs->Delete(adAffectCurrent);

       m_pRs->UpdateBatch(adAffectCurrent);

   }

   catch (_com_error &e)

   {

       GenerateError(e.Error(), e.Description());

   }      

   //RefreshBoundData();  

   Open( _T("VIRUS"));

}

void CRsCgDlg::OnEdit()

{

   // TODO: Add your control notification handler code here

   CVirusRecordDlg dlg;

   // 추가창 모드로 연다.

   dlg.m_nMode = MODE_EDIT;

   dlg.m_sName = (LPCTSTR)(_bstr_t)(_variant_t)(m_pRs->Fields->GetItem("NAME")->Value);

   dlg.m_sInfo = (LPCTSTR)(_bstr_t)(_variant_t)(m_pRs->Fields->GetItem("INFO")->Value);

   dlg.m_sSize = (LPCTSTR)(_bstr_t)(_variant_t)(m_pRs->Fields->GetItem("SIZE")->Value);

   dlg.m_sTreatOnEdit = (LPCTSTR)(_bstr_t)(_variant_t)(m_pRs->Fields->GetItem("TREAT")->Value);

   dlg.m_sFileName = (LPCTSTR)(_bstr_t)(_variant_t)(m_pRs->Fields->GetItem("FNAME")->Value);

   

   if( dlg.DoModal() == IDOK )

   {

       CString sBin;

       if( dlg.m_bPathSelected )

       {

           if( !CDBLogic::GetBin( dlg.m_sFilePath , &sBin) )

               return;

       }

       try

       {

           m_pRs->Fields->GetItem("NAME")->put_Value( _variant_t(dlg.m_sName) );

           m_pRs->Fields->GetItem("INFO")->put_Value( _variant_t(dlg.m_sInfo) );

           m_pRs->Fields->GetItem("TREAT")->put_Value( _variant_t(CString(dlg.m_sTreat[0])) );

           if( !sBin.IsEmpty() )

           {

               m_pRs->Fields->GetItem("FNAME")->put_Value( _variant_t(dlg.m_sFileName) );

               m_pRs->Fields->GetItem("SIZE")->put_Value( _variant_t(dlg.m_sSize) );          

               m_pRs->Fields->GetItem("BIN")->put_Value( _variant_t(sBin) );

           }

           m_pRs->Update();

           //m_pRs->Requery(adCmdTable);

           m_pRs->UpdateBatch(adAffectCurrent);

           //RefreshBoundData();  

       }

       catch (_com_error &e)

       {

           GenerateError(e.Error(), e.Description());

       }      

   

       Open( _T("VIRUS"));

   }

}


정리

VC++에서 ADO를 이용해서 데이타베이스 간단한 레코드 폼을 얻고 싶을때 사용할 수 있는 간단한 ADO Data Bind ActiveX 를 사용하는 방법을 알아보았습니다.

"Database Programming" 카테고리의 다른 글
  • DB 작업을 보다 쉽게 해보자...(OTL 소개) (2)2007/01/09
  • ADO for Performance (0)2007/01/09
  • ADO 데이타 바인딩 다이얼로그 얻기 (0)2007/01/09
  • ADO.NET is not built in a day (0)2006/08/12
  • .NET Data Provider(2) (0)2006/08/12
2007/01/09 09:01 2007/01/09 09:01
Posted by webdizen
Tags ADO, 데이타 바인딩
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/2558

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1  Next»

RSS HanRSS
Blog Image
webdizen
이곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (3009)
Webdizen (141)
Life (6)
Diary (16)
Blog (9)
IDEA (2)
Travel (10)
Book (16)
Photo (7)
Movie (8)
Music (14)
Leisure Sports (10)
Funny (6)
Hardware (121)
Software (120)
Windows (5)
Unix & Linux (120)
Installation (5)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (804)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (2)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (4)
Network (66)
Web (79)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • Regular Expression
  • mapping
  • Virtual Memory
  • 접속 로그
  • VBScript
  • CreateProcess()
  • 시스템 관리자
  • CFile
  • Invitation
  • Compiler
  • 두뇌
  • Office
  • NUMA
  • 대학원
  • Humor
  • XHTML
  • Uni-Processor
  • 로그
  • Registry
  • net-snmp

Recent Articles

  • 트위터(Twitter)의 시작!.
  • 청년 리더의 조건.
  • 애플의 타블렛 PC - 아이패드....
  • 미래의 인터페이스 - 육감 기....
  • 기초발성법 동영상 강좌.

Recent Comments

  • 경청... 너무나 중요한데.......
    webdizen 03/22
  • 학교 과제물중 쓰레드에 대하....
    장진혁 03/17
  • 관리자만 볼 수 있는 댓글입....
    비밀방문자 03/12
  • 상대방의 이야기를 열심히 경....
    DoNuts 03/03
  • 좋은글 잘 보고 갑니다..
    Und_hacker 01/08

Recent Trackbacks

  • printf,scanf를 이용한 형식....
    yundream의 프로그래밍 이야기 03/10
  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 2009
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007

Archive

  • 2010/02 (1)
  • 2010/01 (6)
  • 2009/12 (5)
  • 2009/09 (3)
  • 2009/08 (1)

Calendar

«   2010/03   »
일 월 화 수 목 금 토
  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      

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Polarux - Linuxing
      • Rodman®
      • 까만 나비
      • 나를 가꾸는 시간.
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.