আমি কীভাবে একটি সন্নিবেশ সম্পাদন করব এবং ড্যাপারের সাথে identityোকানো পরিচয় ফিরিয়ে দেব?


170

আমি কীভাবে ডাটাবেসে একটি সন্নিবেশ সম্পাদন করব এবং ড্যাপারের সাথে সন্নিবেশিত পরিচয় ফিরিয়ে দেব?

আমি এরকম কিছু চেষ্টা করেছি:

string sql = "DECLARE @ID int; " +
             "INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff); " +
             "SELECT @ID = SCOPE_IDENTITY()";

var id = connection.Query<int>(sql, new { Stuff = mystuff}).First();

তবে এটি কার্যকর হয়নি।

@ মার্ক গ্র্যাভেল উত্তর দেওয়ার জন্য ধন্যবাদ। আমি আপনার সমাধান চেষ্টা করেছি কিন্তু, এখনও একই ব্যতিক্রম ট্রেস নীচে

System.InvalidCastException: Specified cast is not valid

at Dapper.SqlMapper.<QueryInternal>d__a`1.MoveNext() in (snip)\Dapper\SqlMapper.cs:line 610
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in (snip)\Dapper\SqlMapper.cs:line 538
at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param) in (snip)\Dapper\SqlMapper.cs:line 456

উত্তর:


286

আপনি যদি ব্যবহার করেন তবে এটি ইনপুট / আউটপুট প্যারামিটারগুলিকে সমর্থন করে ( RETURNমান সহ ) তবে DynamicParametersএই ক্ষেত্রে সহজ বিকল্পটি সহজভাবে:

var id = connection.QuerySingle<int>( @"
INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff);
SELECT CAST(SCOPE_IDENTITY() as int)", new { Stuff = mystuff});

নোট করুন যে এসকিউএল সার্ভারের আরও সাম্প্রতিক সংস্করণগুলিতে আপনি এই OUTPUTধারাটি ব্যবহার করতে পারেন :

var id = connection.QuerySingle<int>( @"
INSERT INTO [MyTable] ([Stuff])
OUTPUT INSERTED.Id
VALUES (@Stuff);", new { Stuff = mystuff});

11
@ppiotrowicz হুম্ম .... ছদ্মবেশী স্কুল ফিরে আসতে চলেছে numeric, তাই না? সম্ভবত আপনার মূল কোড এবং ব্যবহার করবেন select @id? (এটি কেবল একটি কাস্ট যোগ করে)। ভবিষ্যতে ড্যাপার বিল্ডগুলিতে এটি স্বয়ংক্রিয়ভাবে কাজ করে তা নিশ্চিত করার জন্য আমি একটি নোট তৈরি করব। আপাতত আর একটি বিকল্প হ'ল select cast(SCOPE_IDENTITY() as int)- আবার কিছুটা কুৎসিত। আমি এই ঠিক করব।
মার্ক গ্র্যাভেল

2
@ মার্কগ্রাভেল: বাহ! গ্রেট মার্ক, এটি একটি ভাল! আমি বুঝতে পারিনি যে scope_identityরিটার্নের ধরণটি numeric(38,0)। সত্যই একটি ভাল ফলাফল +1। যদিও এটি সত্যই নয় এবং আমি নিশ্চিত যে আমি একমাত্র নই।
রবার্ট কোরিটনিক

5
আরে, এই উত্তরটি ডিপার কোয়েরি থেকে একটি পরিচয় মান ফিরে পাওয়ার জন্য এক নম্বর হিট। আপনি উল্লেখ করেছেন যে কোনও বস্তুর সাথে আবদ্ধ হওয়ার পরে এটি অত্যন্ত উন্নত হয়; আপনি কীভাবে এখন এটি করতে চান তা আপনি সম্পাদনা করে আপডেট দিতে পারবেন? আমি আপনার Nov26'12 মন্তব্যটির কাছে গিথুবে টেস্ট ফাইলটিতে সংশোধনগুলি পরীক্ষা করেছি তবে প্রশ্নের সাথে সম্পর্কিত কিছু দেখতে পাচ্ছি না: / আমার ধারণা Query<foo>যে সন্নিবেশ করানো মানগুলির সাথে হয় তারপরে * যেখানে id = SCOPE_IDENTITY () নির্বাচন করে।

2
@ জারেক্সস আপনাকে কী মনে করে এটি সিকিউএস লঙ্ঘন করে? এসকিউএল কোনও এসকিউএল অপারেশন গ্রিডটি দেয় কিনা সে সম্পর্কে নয়। এটি একটি আদেশ, খাঁটি এবং সহজ। শব্দটি ব্যবহার করা সত্ত্বেও এটি সিকিউএসের পদগুলিতে কোনও প্রশ্ন নয় Query
মার্ক গ্রাভেল

3
নিতপিকি, তবে পরিবর্তিত Queryসংগ্রহ থেকে প্রথম মানটি ব্যবহার ও ব্যবহার না করে , আমি মনে করি যে এক্ষেত্রে ExecuteScalar<T>আরও একটি মান সাধারণত ফিরে আসে বলে এই ক্ষেত্রে আরও বোধ করা যায়।
পিটার মাজেদ

53

কেবি: 2019779 , "এসসিপিপিআইডিআইএনডিটি () এবং @@ পরিচয় ব্যবহার করার সময় আপনি ভুল মানগুলি পেতে পারেন", আউটপুট ধারাটি সবচেয়ে নিরাপদ প্রক্রিয়া:

string sql = @"
DECLARE @InsertedRows AS TABLE (Id int);
INSERT INTO [MyTable] ([Stuff]) OUTPUT Inserted.Id INTO @InsertedRows
VALUES (@Stuff);
SELECT Id FROM @InsertedRows";

var id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();

14
এফওয়াইআই, এটি SCOPE_IDENTITY ব্যবহারের চেয়ে ধীর হতে পারে এবং এসকিউএল সার্ভার ২০০৮ আর 2 সার্ভিস প্যাক ১
মাইকেল সিলভার

2
@ মিশেলসিলভার আপনি OUTPUT এর আগে SCOPE_IDENTITY বা @@ পরিচয় ব্যবহারের পরামর্শ দিচ্ছেন ? কিলোবাইট: 2019779 ছিল FIXED ?
কিকিনেট

1
@ কিকিনেট, যদি আমি কোনও ডিবি-র বিরুদ্ধে কোডটি লিখতাম যা স্থির হয়নি, তবে আমি সম্ভবত OUTPUT ধারাটি এটি প্রত্যাশা মতো কাজ করে তা নিশ্চিত করার জন্য ব্যবহার করব।
মাইকেল সিলভার

1
@ এটি একটি একক রেকর্ড সন্নিবেশ করানোর জন্য দুর্দান্ত কাজ করে তবে যদি আমি একটি সংগ্রহটি পাস করিAn enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context
MaYaN

44

একজন প্রয়াত উত্তর, কিন্তু এখানে একটি হল বিকল্প থেকে SCOPE_IDENTITY()উত্তরগুলি আমরা ব্যবহার শেষ পর্যন্ত: আউটপুট ঢোকানো

Sertedোকানো বস্তুর কেবল আইডি ফেরান:

এটি আপনাকে rowোকানো সারির সমস্ত বা কিছু বৈশিষ্ট্য পেতে দেয়:

string insertUserSql = @"INSERT INTO dbo.[User](Username, Phone, Email)
                        OUTPUT INSERTED.[Id]
                        VALUES(@Username, @Phone, @Email);";

int newUserId = conn.QuerySingle<int>(insertUserSql,
                                new
                                {
                                    Username = "lorem ipsum",
                                    Phone = "555-123",
                                    Email = "lorem ipsum"
                                }, tran);

আইডি সহ sertedোকানো বস্তুটি ফিরুন:

আপনি চাইলে আপনি Phoneএবং Emailএমনকি পুরো inোকানো সারিটি পেতে পারেন:

string insertUserSql = @"INSERT INTO dbo.[User](Username, Phone, Email)
                        OUTPUT INSERTED.*
                        VALUES(@Username, @Phone, @Email);";

User newUser = conn.QuerySingle<User>(insertUserSql,
                                new
                                {
                                    Username = "lorem ipsum",
                                    Phone = "555-123",
                                    Email = "lorem ipsum"
                                }, tran);

এছাড়াও, এটির সাহায্যে আপনি মুছে ফেলা বা আপডেট হওয়া সারিগুলির ডেটা ফেরত দিতে পারেন । আপনি যদি ট্রিগার ব্যবহার করছেন তবে কেবল সতর্ক হন কারণ:

OUTPUT থেকে ফিরে আসা কলামগুলি ডেটা প্রতিবিম্বিত করে যেমন এটি INSERT, আপডেট, বা বিলোপ বিবৃতি সম্পন্ন হওয়ার পরে কিন্তু ট্রিগারগুলি কার্যকর হওয়ার আগে।

ট্রিগারগুলির ইনস্ট্যান্টের জন্য, প্রত্যাবর্তিত ফলাফলগুলি এমনভাবে উত্পন্ন হয় যেন ট্রেনার ক্রিয়াকলাপের ফলে কোনও পরিবর্তন ঘটে না থাকলেও প্রকৃতপক্ষে INSERT, আপডেট বা ডিলিটটি ঘটেছে। যদি একটি বিবৃতি যাতে একটি OUTPUT ধারা অন্তর্ভুক্ত থাকে কোনও ট্রিগারটির শরীরে ব্যবহার করা হয়, OUTPUT এর সাথে যুক্ত সন্নিবেশিত এবং মুছে ফেলা টেবিলের সাথে নকলকরণের কলাম রেফারেন্সগুলি এড়াতে ট্রিগারটি সন্নিবেশকৃত এবং মুছে ফেলা সারণীগুলি উল্লেখ করতে অবশ্যই টেবিল এলিয়াস ব্যবহার করতে হবে।

ডক্সে আরও এটি: লিঙ্ক


1
ক্যোয়ারী ব্যবহার করার জন্য @ কুইকিট ট্রানজেকশনস্কোপ অবজেক্ট। আরো এখানে পাওয়া যেতে পারে: dapper-tutorial.net/transaction এবং এখানে: stackoverflow.com/questions/10363933/...
Tadija Bagarić

আমরা কি এখানে 'কোয়েরি সিঙ্গল <int>' এর পরিবর্তে 'এক্সিকিউটস্ল্যাকারেন্সিক <int>' ব্যবহার করতে পারি?
এবলমে

6

আপনি যে অবৈধ কাস্টেক্সেক্সপশনটি পেয়ে যাচ্ছেন তা হ'ল SCOPE_IDENTITY দশমিক (38,0) হওয়ার কারণে ।

আপনি নিম্নলিখিত হিসাবে এটি castালাই দ্বারা এটি একটি int হিসাবে ফেরত করতে পারেন:

string sql = @"
INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff);
SELECT CAST(SCOPE_IDENTITY() AS INT)";

int id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();

4

নিশ্চিত নয় যে এটি কারণ আমি এসকিউএল 2000 এর বিপরীতে কাজ করছি বা না তবে এটি কাজ করতে আমাকে এই কাজটি করতে হয়েছিল।

string sql = "DECLARE @ID int; " +
             "INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff); " +
             "SET @ID = SCOPE_IDENTITY(); " +
             "SELECT @ID";

var id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();

2
<কোড> নির্বাচন করুন কাস্ট (SCOPE_IDENTITY () হিসাবে পূর্বে) </ কোড> চেষ্টা করুন এবং এটি 2000 এও কাজ করা উচিত।
ডেভিড আলেউ

আপনি চেষ্টা করেছেন select cast(SCOPE_IDENTITY() as int)?
কিকিনেট

1

আপনার জীবনকে আরও সহজ করে তুলতে একটি দুর্দান্ত গ্রন্থাগার রয়েছে ড্যাপার.কন্ট্রিবি.এক্সটেনশনগুলি। এটি অন্তর্ভুক্ত করার পরে আপনি কেবল লিখতে পারেন:

public int Add(Transaction transaction)
{
        using (IDbConnection db = Connection)
        {
                return (int)db.Insert(transaction);
        }
}

0

আপনি যদি ড্যাপার ব্যবহার করেন সিম্পলসেভ:

 //no safety checks
 public static int Create<T>(object param)
    {
        using (SqlConnection conn = new SqlConnection(GetConnectionString()))
        {
            conn.Open();
            conn.Create<T>((T)param);
            return (int) (((T)param).GetType().GetProperties().Where(
                    x => x.CustomAttributes.Where(
                        y=>y.AttributeType.GetType() == typeof(Dapper.SimpleSave.PrimaryKeyAttribute).GetType()).Count()==1).First().GetValue(param));
        }
    }

ড্যাপার.সিম্পলসেভ কী?
কিকিনেট

@ কিরকুইনেট, আমি কিছুক্ষণ আগে কাজ করেছি এমন একটি প্রকল্পে আমি ড্যাপার, ডাপার.সিম্পলসিআরডি, ডাপার.সিম্পলসিআরডি.মডেলজেনেটর, ড্যাপার.সিম্পললড এবং ড্যাপার.সিম্পলস্যাভ ব্যবহার করেছি। আমি সেগুলি নিউগেট আমদানির মাধ্যমে যুক্ত করেছি। আমি তাদের টি-টেমপ্লেটের সাথে একত্রিত করে আমার সাইটের সমস্ত ডিএও-র স্ক্যাফোল্ড করে। github.com/Paymentsense/Dapper.SimleSave github.com/Paymentsense/Dapper.SimpleLoad
Lodlaiden
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.