質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • C#

    7134questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C#とSQL文 mdfファイルのdataをSQLserverに追加したい SqlBulkCopyでロケールID違いのエラー

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,167

hamaa

score 35

素人ですみません。(質問を2人の意見を聞いて再編集しました。)
素人なので変な風に理解してるかもしれません!よろしくお願いします。

ローカルにあるmdfファイルのテーブルごと
違うPCのSQLserverのテーブルに追加したいです。。
↓例 追加したいmdfファイルのデータ

A_field B_field C_field D_field
LCno1   名前1  電話1  メール1
LCno2   名前2  電話2  メール2
LCno3   名前3  電話3  メール3


↓SQLserverのテーブル 追加後こうなってほしい (0_fieldは自動採番(オートナンバー)field)

0_field  A_field B_field C_field D_field
All_No1  LCno1   名前1    電話1  メール1
All_No2  LCno2   名前2    電話2  メール2
All_No3  LCno3   名前3    電話3  メール3


この様に共有サーバーに更新したいのですが… 
2つ浮かびましたが…
・1のパターン SQL文で一括
・2のパターン insert文をC#で書いて一行つつでなら… (LINQも使える??)
2のパターンは何回もinsertするのでサーバーに負担かかりませんか?
今回は1のパターンを思考しています。。
↓ 1のパターンで考えた場合 (ごめんなさい2のパターンまで頭が回ってません。。。)

SQL接続文字 = @"Data Source=…"

INSERT文 ="INSERT INTO SQLserverのテーブル 名 (A_field,B_field,C_field,D_field)
SELECT * FROM [mdfデータベース名].テーブル名 WHERE 条件のあるフィールド = 何らか条件"

      
★問題点★
[mdfデータベース名]この部分

[mdfデータベース名]visual studioで追加してるから、mdfファイル名(サーバー名でだけいい?)
→やってみたが駄目だった。(.mdfまで書く?)
[フルパス + mdfデータベース名](.mdfまで書く?)
→ちょっと、やってみたがうまく行かず…
③プロバイダみたいなものが必要?
[Provider=]or[Driver=]???mdf用の書き方がいまいち分からない

そもそもこのやり方でうまく行かないのか…

↓つくったINERT文をこれで

 SQL接続.ExecuteNonQuery(INSERT文, SQL接続文字);


↓SQL接続クラス

public class SQL接続
{
public static void ExecuteNonQuery(string sql, string 接続文字列)
 {
using (SqlCommand command = new SqlCommand())
 {
 SqlConnection conn = new SqlConnection();
 conn.ConnectionString = conn.ConnectionString = 接続文字列;
 // トランザクションを開始します。
conn.Open();
 SqlTransaction transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);
 try
 {
 command.CommandText = sql;
 command.Connection = conn;
 command.Transaction = transaction;
 command.ExecuteNonQuery();
 //トランザクションをコミットします。
transaction.Commit();
 }
 catch (System.Exception)
 {
 //トランザクションをロールバックします。
transaction.Rollback();
 throw;                     ← ここでエラーになってる
 }
 finally
 {
 conn.Close();
 }
 }
 }


tamotoさんのをコメントをみて ↑あきらめて…
1/17追記 新解決策 SqlBulkCopy あと一歩で解決か!?汗。。

public static void ExecuteCopy(string tableName)
        {
            using (var mdfcn =  new SqlConnection(mdf接続文字列))
            using (var SQLcn = new SqlConnection(SQLserver接続文字))
            {
                mdfcn.Open();
                SQLcn.Open();

                var mdfsql = string.Format("SELECT * FROM [{0}]", tableName);
                var mdfcmd = new SqlCommand(mdfsql, mdfcn);
                using (var rd = mdfcmd.ExecuteReader())
                {
                    using (var bulk = new SqlBulkCopy(SQLcn))
                    {
                        bulk.BulkCopyTimeout = 10000;
                        bulk.DestinationTableName = string.Format("dbo.{0}",tableName);
                        bulk.WriteToServer(rd);    //← ここでエラー ロケールIDが 
                          //追加情報:ソース列 'フィルード名' のロケール ID '1033' と
                               //ターゲット列 'フィルード名' のロケール ID '1041' は
                              //一致していません。
                    }

                }

            }

あと一歩なのかロケールIDが一致しないといわれる。
このやり方でSQLserver側の0fieldが mdf側になくても行けるのかがいまいち分かりませんが
ただ '1033'→英語 '1041'→日本語を指定出来るのかな… ?? またググってる最中です。

2017/02/06追記 修正箇所

using (DataTable datatable = new DataTable())// 2017/02/06追記
{// 2017/02/06追記
    datatable.Load(rd);// 2017/02/06追記
    using (var bulk = new SqlBulkCopy(SQLcn))
    {
        bulk.BulkCopyTimeout = 10000;
        bulk.DestinationTableName = string.Format("dbo.{0}",tableName);
        bulk.WriteToServer(datatable);    //2017/02/06 書換
    }
}// 2017/02/06追記


tomatoさんのアドバイスで完璧にクリアできました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

SQLServerManagementStudioを使ってのデータベースのインポートとは違うのですか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/12 20:17

    データベースのインポートは違うかな…冷汗(素人で分かりません。)
    ローカルにmdfファイルをいてデータ管理してます。
    それを共有サーバーに更新したいのですが… 
    SQL文?一括?? それとも insert文を一行つつでなら
    C#で書いて掛けそうですが… 
    SqlDataAdapterとか?
    SqlConnectionでかな?
    のやり方がいまいち分からないので… 

    キャンセル

  • 2017/01/13 01:46

    ローカルのmdfのデータをSQLServer側に移したい(Insert)したいのですよね
    その時にローカルのmdfよりSQLServer側のテーブルの方が拡張されている(例示だと0_fieldが追加されている)ということですよね
    1回ものの話ならインポートしてあげれば済む話だと思いますが..
    もしこれが反復して起こるなら2回目以降の時にSQLServer側にあるレコードならUpdate、ないレコードならInsertとして扱ってあげないといけないと思います
    ただしそういう時にはレコードを一意に特定できるフィールド(所謂主キー)を定義しておいてあげる必要があります

    コードよりデータベースのことをもう少し知った方が捗ると思いますよ

    キャンセル

  • 2017/01/13 15:56

    失礼しました。
    INSERT INTO SQLserverのテーブル 名 (A_field,B_field,C_field,D_field)
    SELECT * FROM mdfファイルのテーブル名.[ココ?] WHERE 条件のあるフィールド = 何らか条件

    だとは 思うのですが… 接続部分の書き方?
    [ココ?]と 書いたところ 後は通常時のSQLサーバーのconnectionの書き方で良いのでしょうか?

     

    キャンセル

  • 2017/01/13 17:55 編集

    「INSERT ~ SELECT ~」はそのデータベースから見えるデータベースのテーブルに対してまでじゃなかったかな?
    なんかリンクサーバーとかにも手を出さないといけない感じじゃないですかね
    もしローカルにあるmdfがSQLServerから見えてたら
    > mdfファイルのテーブル名.[ココ?]
    の部分は
    mdfデータベース名.テーブル名
    でいけると思いますが

    それなら地道にコードから、ローカルのmdfファイルに対するコネクションと、SQLServerに対するコネクションを張って、SelectとInsertを繰り返した方が手っ取り早い気がする

    キャンセル

  • 2017/01/16 15:08

    dojikkoさん
    ありがとうございます。
    SQL接続文字 = @"Data Source=…"

    INSERT文 ="INSERT INTO SQLserverのテーブル 名 (A_field,B_field,C_field,D_field)
    SELECT * FROM mdfデータベース名.テーブル名 WHERE 条件のあるフィールド = 何らか条件"
                ↓
             ①visual studioで追加してるから、mdfファイル名(サーバー名でだけいい?)
             →やってみたが駄目だった。
             ②ここの部分がフルパスだけでいい?
             →ちょっとちやってみます。
             ③プロバイダみたいなものが必要?
             →???

    SQL接続.ExecuteNonQuery(INSERT文, SQL接続文字);

    ↓SQL接続クラス

    public class SQL接続
    {
    public static void ExecuteNonQuery(string sql, string 接続文字列)
    {
    using (SqlCommand command = new SqlCommand())
    {
    SqlConnection conn = new SqlConnection();
    conn.ConnectionString = conn.ConnectionString = 接続文字列;
    // トランザクションを開始します。
    conn.Open();
    SqlTransaction transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);
    try
    {
    command.CommandText = sql;
    command.Connection = conn;
    command.Transaction = transaction;
    command.ExecuteNonQuery();
    //トランザクションをコミットします。
    transaction.Commit();
    }
    catch (System.Exception)
    {
    //トランザクションをロールバックします。
    transaction.Rollback();
    throw;
    }
    finally
    {
    conn.Close();
    }
    }
    }

    キャンセル

checkベストアンサー

0

こんにちは。
いまいち質問の意味がわかってないのですが……

  • どんどん更新されるmdfの中身を逐一SQLServerに放り込みたい(何度もデータを放り込みたい)
  • 今までmdfで管理してたデータをこれからはSQLServerで扱いたい(1回限り、全データを放り込みたい)

この2つのうち、後者が目的だと思うのですが、あってますでしょうか?
後者を行う場合、SQLServerのGUI(SQL Server Management Studio)にmdfの中身を丸ごとSQLServerにインポートする機能があったと思うのですが、それを使うのではダメなんですかね?SQL文を書くとか書かないとかそれ以前の話ですよ。。


01/17追記
ローカルのmdfからリモートへデータを追記する方針は変わらないということなので、その方向で回答してみます。

まず、根本的な勘違いがある可能性があります。
ローカルのSQL Server(mdfファイル)とリモートのSQL Serverは「別のSQLサーバ」なので、一つのSQL文でデータを移行するのは不可能です。(正確には、リンクサーバとかのサーバ側の機能を利用すればできるのかもしれないですが、あんまり詳しくないので今回は無視します)
つまり、2つのサーバ間でデータを移行するためには、「ローカルmdfに接続するSQLConnection」と「リモートSQL Serverに接続するSQLConnection」の2つの接続が必要なのです。
それぞれ別々に考えてしまえば、「ローカルからデータを取り出す処理」「リモートにデータを送る処理」の異なる2つの手順を順番に行うだけでいいのです。
まずはデータを取り出す処理だけ実装し、意図したデータが取り出せているかどうか確認してみて下さい。
データが取り出せていれば、後はそれをリモートに放り込むだけです。整合性のチェックとかはがんばってください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/13 16:49

    ローカルのmdfファイルでデータを蓄積しています。
    それを一括での中央管理SQLサーバーにインサートしたい 朝1回です。
    >SQLServerのGUI(SQL Server Management Studio)にmdfの中身を丸ごとSQLServerにインポートする機能があったと思うのですが、
    ↑やっぱりそういう機能あるんですか!? 
    0_fieldが1列多いですが出来そうですか? ちょっと自分でもSQL Server Management Studio もう少し調べてみます 汗

    キャンセル

  • 2017/01/13 16:59

    朝1回ということは、複数回実行するということですか……
    最初の1回はインポート操作でできるはずですが、それ以降は「同期操作」になるので、整合性を考慮してInsert/Updateを行わないといけないので結構大変です。
    一度SQLServerにデータを入れた後は、「ローカル蓄積は止めて」「直接SQLServerの方にデータを蓄積」できるならそっちのほうが楽ですよ。
    というか、上のdojikkoさんの回答とコメントを一文字ずつちゃんと読みなおしてみてください……

    キャンセル

  • 2017/01/13 17:30

    そういった意味だとInsertで大丈夫です。
    更新をする時は個別でします。

    キャンセル

  • 2017/01/16 20:32

    日本語があまりうまくなくて失礼します。
    ローカルでやらなきゃいけない理由としては中央のSQLサーバーにログを残せない時、
    回線切断状態や、SQLサーバーダウン時にも、ローカルでログを残しておきたいからなんです。

    キャンセル

  • 2017/01/17 10:09

    tomotoさんやはりそうなんですね。二つの接続が必要ですよね。
    VBAのようにプロバイダ部分をSQLの中に書けるか探していたんですが…。
    解決策としてググって頑張ってSqlBulkCopyなるものを発見コードを追記します。

    キャンセル

  • 2017/01/17 10:31

    上記に追記しました。 あともう一歩? 勘違いしてたらすいません。汗

    キャンセル

  • 2017/01/17 11:13

    ロケールの不一致についてちょっと調べてみましたがなんだかよくわかりませんね……一応、mdfから読み出したSqlDataReaderを直接BulkCopyせず、一度DataTableに読み込んでからそれを放り込むとうまくいくという情報もありますね。ちょっと調べられる環境がないので間違ってたらすみません。
    それと、SqlDataReaderをそのままリモートSQLServerにBulkCopyすると、リモート側にデータの重複が発生してしまうと思うのですが、そこら辺はどう処理するのでしょう?BulkCopyする前にコピーするデータの加工が必要だと思います。

    キャンセル

  • 2017/01/19 10:33

    >一応、mdfから読み出したSqlDataReaderを直接BulkCopyせず、一度DataTableに読み込んでからそれを放り込むとうまくいくという情報もありますね。
    bulkcopyは高速ですと出ているので、せっかくですのでもう少し調べてみます。 ダメでしたら tamotoさんの方向に変更して探してみます。(><

    キャンセル

  • 2017/01/19 11:03

    あっと、WriteToServerはDbDataReaderを引数に取るもの以外にDataTableをそのまま渡せるオーバーロードが存在するようなので、一旦SqlDataReaderからDataTableに読み込んで、そのDataTableをSqlBulkCopyで放り込めばうまくいくのではないか、という話です。

    キャンセル

  • 2017/01/31 12:19

    tamotoさん 別件の仕事でおくれておりますが、
    >DataTableに読み込んで、そのDataTableをSqlBulkCopyで放り込めばうまくいくのではないか、という話です。
    やってみます。もう少々おまちください。汗

    キャンセル

  • 2017/02/06 16:44

    tamotoさん!!!! ありがとうございます! 別件の仕事で離れておりましたが…
    tamotoさんの言うとおりです!!完璧にできました!! ありがとうございます!!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    7134questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • トップ
  • C#に関する質問
  • C#とSQL文 mdfファイルのdataをSQLserverに追加したい SqlBulkCopyでロケールID違いのエラー