성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
[공진영] 안녕하세요 좋은글 감사합니다. 현재 제가 wpf로 관제 모...
[정성태] The Windows Registry Adventure #1: ...
[정성태] systemd for Developers I ; https:/...
[정성태] 엄밀히 object 타입의 인스턴스가 다른 타입으로 형변환 가능...
[정성태] 아래의 글에서 나오는 "Windows Application Pa...
[정성태] The history of calling conventions,...
[정성태] Secure and Deploy .NET Windows Form...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>TransactionScope에 사용자 정의 트랜잭션을 참여시키는 방법</h1> <p> 오호~~~ 12월 6일 주간 닷넷에,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 주간닷넷 2016년 12월 6일 ; <a target='tab' href='https://learn.microsoft.com/en-us/archive/blogs/eva/주간닷넷-2016년-12월-6일'>https://learn.microsoft.com/en-us/archive/blogs/eva/주간닷넷-2016년-12월-6일</a> </pre> <br /> 재미난 글이 나왔군요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Let .NET framework care about transactions handling for you by implementing IEnlistmentNotification ; <a target='tab' href='https://blog.goyello.com/2016/11/30/let-net-framework-care-about-transactions-handling-for-you-by-implementing-ienlistmentnotification/'>https://blog.goyello.com/2016/11/30/let-net-framework-care-about-transactions-handling-for-you-by-implementing-ienlistmentnotification/</a> </pre> <br /> 바로 TransactionScope에 간이 사용자 정의 트랜잭션을 끼워 넣을 수 있는 IEnlistmentNotification 인터페이스에 대한 소개입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > IEnlistmentNotification ; <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/api/system.transactions.ienlistmentnotification'>https://learn.microsoft.com/en-us/dotnet/api/system.transactions.ienlistmentnotification</a> </pre> <br /> 방법이 생각보다 간단합니다. 그냥 다음과 같이 인터페이스를 구현해 주고, 적당하게 트랜잭션 단계마다 필요한 작업만 해주면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Transactions; class TxObject : <span style='color: blue; font-weight: bold'>IEnlistmentNotification</span> { public TxObject(object objValue) { if (Transaction.Current != null) { Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None); } } <span style='color: blue; font-weight: bold'>public void Commit(Enlistment enlistment) { enlistment.Done(); } public void InDoubt(Enlistment enlistment) { enlistment.Done(); } public void Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); // or, preparingEnlistment.ForceRollback(); } public void Rollback(Enlistment enlistment) { enlistment.Done(); }</span> } class Program { static void Main(string[] args) { <span style='color: blue; font-weight: bold'>using (var tx = new TransactionScope())</span> { TxObject obj = new TxObject(null); <span style='color: blue; font-weight: bold'>tx.Complete();</span> } } } </pre> <br /> 예를 하나 들어볼까요? 가령, 웹 사이트에서 게시판 구현할 때 DB에 게시글 정보를 저장한 후 첨부 파일도 처리할 때가 종종 있습니다. 이럴 때, DB 저장과 첨부 파일 저장을 하나의 트랜잭션으로 묶는 것을 고려할 수 있습니다. 물론, 정확하게 구현하려면 이런 경우 비스타 운영체제부터 지원하는 TxF(Transactional NTFS) 기능을 이용해야 하는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Transactional NTFS (TxF) .NET ; <a target='tab' href='https://txfnet.codeplex.com/'>https://txfnet.codeplex.com/</a> </pre> <br /> 그냥 가볍게 다음과 같은 식으로 구현하는 것도 가능합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.IO; using System.Transactions; class TxFile : IEnlistmentNotification { string _savedPath; string _orgFilePath; string _contents; public TxFile(string filePath, string contents) { _orgFilePath = filePath; _savedPath = filePath; _contents = contents; if (Transaction.Current != null) { _savedPath = string.Format("{0}.in_tx", filePath); Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None); } else { File.WriteAllText(_orgFilePath, _contents); } } public void Commit(Enlistment enlistment) { File.Move(_savedPath, _orgFilePath); enlistment.Done(); } public void InDoubt(Enlistment enlistment) { enlistment.Done(); } public void Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); } public void Rollback(Enlistment enlistment) { if (File.Exists(_savedPath)) { File.Delete(_savedPath); } enlistment.Done(); } public void Save() { File.WriteAllText(_savedPath, _contents); } } class Program { static void Main(string[] args) { string filePath = "c:\\temp\\test.txt"; using (var tx = new TransactionScope()) { // ... [트랜잭션에 참여하는 SQL 코드 생략] ... TxFile file = new TxFile(filePath, "test is good"); file.Save(); // throw new ApplicationException("Exception occurred!"); tx.Complete(); } } } </pre> <br /> 위의 코드를 실행해 보면, tx.Complete(); 시점에 정상적으로 파일이 생성되는 반면 중간에 "// throw ..." 주석을 해제하거나 tx.Complete() 호출을 제거하면 Rollback 메서드의 호출로 인해 파일이 삭제가 됩니다.<br /> <br /> 물론, TxF(Transactional NTFS)만큼 정교한 트랜잭션을 구현하려면 트랜잭션 로그 파일도 기록하는 등의 작업도 해야 하지만 그럴 거면 차라리 TxF를 사용하는 것이 더 낫습니다.<br /> <br /> <hr style='width: 50%' /> <br /> 그러고 보니, 예전에 Python에서 __enter__, __exit__ 기능을 활용한 with 문 구현에서 "값 변경에 따른 트랜잭션 구현"을 설명한 적이 있는데요. <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Python의 zip과 with 문 context를 C#과 비교하면. ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/1371'>http://www.sysnet.pe.kr/2/0/1371</a> </pre> <br /> 이것도 다음과 같은 식으로 유사하게 구현해 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public class ValueTransaction<T> : IEnlistmentNotification { T _orgValue; T _value; public T Value { get { return _value; } } public ValueTransaction(T value) { _orgValue = value; _value = value; if (Transaction.Current != null) { Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None); } } public void SetValue(T newValue) { _value = newValue; } public void Commit(Enlistment enlistment) { enlistment.Done(); } public void InDoubt(Enlistment enlistment) { enlistment.Done(); } public void Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); // or preparingEnlistment.ForceRollback(); } public void Rollback(Enlistment enlistment) { _value = _orgValue; enlistment.Done(); } } class Program { static void Main(string[] args) { ValueTransaction<int> myValue = null; try { using (var tx = new TransactionScope()) { myValue = new ValueTransaction<int>(6); myValue.SetValue(5); // throw new ApplicationException("TEST"); tx.Complete(); } } catch { } if (myValue != null) { Console.WriteLine(myValue.Value); } } } </pre> <br /> 뭐,,, 대충 비슷한가요? ^^<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1089&boardid=331301885'>첨부 파일은 본문의 예제 코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1360
(왼쪽의 숫자를 입력해야 합니다.)