성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Understanding the classical model f...
[정성태] DLL이기 때문에 self-contained로 배포해도 (주체적...
[정성태] // 해당 디렉터리에서 가장 최신의 파일을 대상으로 tail 명...
[정성태] Misunderstanding the “Prevent acces...
[정성태] 본문에서 Elliptic Curve를 이용한 서명을 다뤘는데요,...
[이상준] 안녕하세요 정성태님! 링크하신 글의 원문을 적은 사람입니다. ...
[정성태] 저도 거기까진 해본 적이 없습니다. 단지, ffmpeg를 보면,...
[sk hyun] 안녕하세요. 좋은 글 잘 보고 있습니다. 질문이 있습니다....
[정성태] How can I tell whether two programs...
[정성태] The case of the fail-fast crashes c...
글쓰기
제목
이름
암호
전자우편
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'>C# - 닷넷 응용 프로그램에서 SQLite 사용 (System.Data.SQLite)</h1> <p> 예전에 소개한 글은,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - 닷넷 응용 프로그램에서 SQLite 사용 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12138'>https://www.sysnet.pe.kr/2/0/12138</a> </pre> <br /> Microsoft.Data.SQLite를 사용했었는데요, 이번엔 System.Data.SQLite를 사용해 보겠습니다. 사실, 지난 글을 보셨으면 이번에도 단순하게 해결할 수 있습니다. 우선 nuget 참조를 하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Install-Package <a target='tab' href='https://www.nuget.org/packages/System.Data.SQLite'>System.Data.SQLite</a> </pre> <br /> 코딩은 "<a target='tab' href='https://www.sysnet.pe.kr/2/0/12138'>C# - 닷넷 응용 프로그램에서 Sqlite 사용</a>" 글을 거의 그대로 다음과 같이 포팅할 수 있습니다.<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.Data.SQLite; using System.Data; namespace ConsoleApp1 { class Program { static void Main(string[] args) { string currentPath = Path.GetDirectoryName(typeof(Program).Assembly.Location); if (string.IsNullOrEmpty(currentPath) == true) { return; } string sqlFilePath = Path.Combine(currentPath, "test.sqlite"); string connectionString = $"Data Source={sqlFilePath};"; using (SQLiteConnection connection = new SQLiteConnection(connectionString)) { connection.Open(); CreateTableIfNotExists(connection); // Create SQLiteCommand insertCommand = new SQLiteCommand(); insertCommand.Connection = connection; insertCommand.CommandText = "INSERT INTO mytable(id, NAME, age, DESCRIPTION) VALUES (@id, @NAME, @age, @DESCRIPTION)"; insertCommand.Parameters.Add("@id", DbType.Int32); insertCommand.Parameters.Add("@NAME", DbType.String, 50); insertCommand.Parameters.Add("@age", DbType.Int32); insertCommand.Parameters.Add("@DESCRIPTION", DbType.String, 150); string nameValue = "Name" + Guid.NewGuid().ToString(); insertCommand.Parameters[0].Value = (int)DateTime.Now.Ticks; insertCommand.Parameters[1].Value = nameValue; insertCommand.Parameters[2].Value = 10; insertCommand.Parameters[3].Value = nameValue + "_Description"; int affected = insertCommand.ExecuteNonQuery(); Console.WriteLine("# of affected row: " + affected); // Update SQLiteCommand updateCommand = new SQLiteCommand(); updateCommand.Connection = connection; updateCommand.CommandText = "UPDATE mytable SET DESCRIPTION=@DESCRIPTION WHERE NAME=@NAME"; updateCommand.Parameters.Add("@NAME", DbType.String, 50); updateCommand.Parameters.Add("@DESCRIPTION", DbType.String, 150); updateCommand.Parameters[0].Value = nameValue; updateCommand.Parameters[1].Value = nameValue + "_Description2"; affected = updateCommand.ExecuteNonQuery(); Console.WriteLine("# of affected row: " + affected); // Select - ExecuteScalar SQLiteCommand selectCommand = new SQLiteCommand(); selectCommand.Connection = connection; selectCommand.CommandText = "SELECT count(*) FROM mytable"; object result = selectCommand.ExecuteScalar(); Console.WriteLine("# of records: " + result); // Select - DataTable DataSet ds = new DataSet(); /* DataAdapter 미구현 SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM mytable", sqlConnection); da.Fill(ds, "mytable"); DataTable dt = ds.Tables["mytable"]; foreach (DataRow dr in dt.Rows) { Console.WriteLine(string.Format("Name = {0}, Desc = {1}", dr["NAME"], dr["DESCRIPTION"])); } */ // Delete SQLiteCommand deleteCommand = new SQLiteCommand(); deleteCommand.Connection = connection; deleteCommand.CommandText = "DELETE FROM mytable WHERE NAME=@NAME"; deleteCommand.Parameters.Add("@NAME", DbType.String, 50); deleteCommand.Parameters[0].Value = nameValue; affected = deleteCommand.ExecuteNonQuery(); Console.WriteLine("# of affected row: " + affected); } } private static void CreateTableIfNotExists(SQLiteConnection conn) { string sql = "create table if not exists mytable(id int, NAME varchar(50), age int, DESCRIPTION varchar(150))"; using (SQLiteCommand command = new SQLiteCommand(sql, conn)) { command.ExecuteNonQuery(); } sql = "create index if not exists idx_NAME on mytable(NAME)"; using (SQLiteCommand command = new SQLiteCommand(sql, conn)) { command.ExecuteNonQuery(); } } } } </pre> <br /> .NET Core/5+ 프로젝트에서 저렇게 사용한 경우, 배포까지 쉽게 됩니다. 비주얼 스튜디오에서 "Publish" 메뉴를 이용해 처리하면 출력 디렉터리에 다음과 같은 구조로 배포가 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ConsoleApp1.deps.json ConsoleApp1.dll ConsoleApp1.exe ConsoleApp1.pdb ConsoleApp1.runtimeconfig.json EntityFramework.dll EntityFramework.SqlServer.dll Microsoft.Win32.SystemEvents.dll System.CodeDom.dll System.Configuration.ConfigurationManager.dll System.Data.SqlClient.dll System.Data.SQLite.dll System.Data.SQLite.EF6.dll System.Drawing.Common.dll System.Security.Cryptography.ProtectedData.dll System.Security.Permissions.dll System.Windows.Extensions.dll [runtimes] [linux-x64] [native] SQLite.Interop.dll [osx-x64] [native] SQLite.Interop.dll [unix] ...[생략]... [win] ...[생략]... [win-arm64] [native] sni.dll [win-x64] [native] sni.dll SQLite.Interop.dll [win-x86] [native] sni.dll SQLite.Interop.dll </pre> <br /> 다른 PC에서 실행하려면 그냥 위의 파일들을 전부 복사해 주면 됩니다. 물론, 대상 환경에 따라 적절하게 "runtimes" 하위에 있는 디렉터리는 골라서 배포하셔도 됩니다. 예를 들어, 64비트 콘솔 응용 프로그램이라면 "./runtimes/win-x64/native" 디렉터리만 포함할 수 있습니다. (신경 쓰기 싫으면 그냥 다 복사하시고.)<br /> <br /> 참고로, SQLite 관련 DLL들이 "./runtimes/win-x64/native" 서브 디렉터리에 없어도 됩니다. 플랫폼 고려를 하지 않는다면 그냥 대상 DLL만 루트에 포함시켜도 됩니다. 따라서 64bit 윈도우 응용 프로그램이라면 다음과 같이 배포해도 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ConsoleApp1.deps.json ConsoleApp1.dll ConsoleApp1.exe ConsoleApp1.pdb ConsoleApp1.runtimeconfig.json EntityFramework.dll EntityFramework.SqlServer.dll Microsoft.Win32.SystemEvents.dll System.CodeDom.dll System.Configuration.ConfigurationManager.dll System.Data.SqlClient.dll System.Data.SQLite.dll System.Data.SQLite.EF6.dll System.Drawing.Common.dll System.Security.Cryptography.ProtectedData.dll System.Security.Permissions.dll System.Windows.Extensions.dll <span style='color: blue; font-weight: bold'>sni.dll</span> // 상황에 따라 sni.dll은 없어도 됩니다. <span style='color: blue; font-weight: bold'>SQLite.Interop.dll</span> </pre> <br /> 만약 EXE와 같은 디렉터리든, 서브 디렉터리든 관련 DLL이 없으면 이런 예외가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > c:\temp>ConsoleApp1.exe Unhandled exception. System.DllNotFoundException: Unable to load DLL 'SQLite.Interop.dll' or one of its dependencies: The specified module could not be found. (0x8007007E) at System.Data.SQLite.UnsafeNativeMethods.sqlite3_config_none(SQLiteConfigOpsEnum op) at System.Data.SQLite.SQLite3.StaticIsInitialized() at System.Data.SQLite.SQLiteLog.PrivateInitialize(String className) at System.Data.SQLite.SQLiteLog.Initialize(String className) at System.Data.SQLite.SQLiteConnection..ctor(String connectionString, Boolean parseViaFramework) at System.Data.SQLite.SQLiteConnection..ctor(String connectionString) at ConsoleApp1.Program.Main(String[] args) </pre> <br /> <hr style='width: 50%' /><br /> <br /> 그렇다면 .NET Framework 프로젝트라면 어떻게 될까요? 일단, "Install-Package System.Data.SQLite" 명령어로 참조 추가는 동일하게 할 수 있습니다. 또한 소스코드도 위의 내용을 그대로 복붙해도 (당연히) 빌드가 됩니다.<br /> <br /> 배포도 해볼까요? 일단, 해당 프로젝트를 빌드하면 다음과 같은 구조로 파일들이 출력됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ConsoleApp1.exe ConsoleApp1.exe.config ConsoleApp2.pdb EntityFramework.dll EntityFramework.SqlServer.dll EntityFramework.SqlServer.xml EntityFramework.xml System.Data.SQLite.dll System.Data.SQLite.EF6.dll System.Data.SQLite.Linq.dll System.Data.SQLite.xml [x64] SQLite.Interop.dll [x86] SQLite.Interop.dll </pre> <br /> 다른 거 할 필요 없습니다. 위의 디렉터리 구조 그대로 다른 PC에 복사하면 역시 실행이 잘됩니다.<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=2072&boardid=331301885'>첨부 파일은 이 글의 .NET 7/.NET Framework 4.8 예제 코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1127
(왼쪽의 숫자를 입력해야 합니다.)