डैपर के साथ आवेषण और अद्यतन करना


195

मैं डॅपर का उपयोग करने में दिलचस्पी रखता हूं - लेकिन जो मैं इसे बता सकता हूं वह केवल क्वेरी और एक्सक्यूट का समर्थन करता है। मैं यह नहीं देखता कि डैपर में ऑब्जेक्ट्स को सम्मिलित और अद्यतन करने का एक तरीका शामिल है।

यह देखते हुए कि हमारी परियोजना (अधिकांश परियोजनाओं?) को आवेषण और अपडेट करने की आवश्यकता है, डैपर के साथ इंसर्ट और अपडेट करने के लिए सबसे अच्छा अभ्यास क्या है?

अधिमानतः हमें पैरामीटर बिल्डिंग आदि के ADO.NET विधि का सहारा नहीं लेना होगा।

इस बिंदु पर मैं जो सबसे अच्छा उत्तर दे सकता हूं, वह है आवेषण और अपडेट के लिए LinqToSQL का उपयोग करना। क्या कोई बेहतर जवाब है?


3
Dapper.NET से ही यह Contrib extension है जो मैं उपयोग करता हूँ। github.com/StackExchange/dapper-dot-net/tree/master/…
राजीव

जवाबों:


201

हम कुछ सहायकों के निर्माण पर विचार कर रहे हैं, अभी भी एपीआई पर निर्णय ले रहे हैं और यदि यह कोर में जाता है या नहीं। देखें: प्रगति के लिए https://code.google.com/archive/p/dapper-dot-net/issues/6

मतलब समय में आप निम्न कार्य कर सकते हैं

val = "my value";
cnn.Execute("insert into Table(val) values (@val)", new {val});

cnn.Execute("update Table set val = @val where Id = @id", new {val, id = 1});

और इसी तरह और भी

मेरी ब्लॉग पोस्ट भी देखें: वह कष्टप्रद INSERT समस्या

अपडेट करें

जैसा कि टिप्पणियों में बताया गया है, अब इन एक्सटेंशन विधियों के रूप में Dapper.Contrib परियोजना में कई एक्सटेंशन उपलब्ध हैं IDbConnection:

T Get<T>(id);
IEnumerable<T> GetAll<T>();
int Insert<T>(T obj);
int Insert<T>(Enumerable<T> list);
bool Update<T>(T obj);
bool Update<T>(Enumerable<T> list);
bool Delete<T>(T obj);
bool Delete<T>(Enumerable<T> list);
bool DeleteAll<T>();

4
हाय सैम, गूगल के साथ अपने तो जवाब मिल गया है और मैं सोच रहा था कि अगर कोड की अंतिम पंक्ति शब्द को शामिल करना चाहिए setके रूप में cnn.Execute("update Table SET val = @val where Id = @id", new {val, id = 1});या इस व्यवसायिक विशिष्ट है? मैं डैपर के लिए नया हूं और एक अद्यतन उदाहरण की तलाश कर रहा हूं :)
जेपी हेल्लेमन्स

1
@JPHellemons मैंने यह कोशिश की var updateCat = connection.Execute("UPDATE tCategories SET sCategory = @val WHERE iCategoryID = @id", new { val = "dapper test", id = 23 });और यह काम किया। SET के उपयोग के बिना मुझे sCategory के पास एक SQLException सिंटैक्स त्रुटि मिलती है।
प्रिव्यू

3
दिसंबर 2015 तक तेजी से आगे: github.com/StackExchange/dapper-dot-net/tree/master/…
Rosdi Kasim

3
@RosdiKasim क्या यह डॅपर का उपयोग करने के उद्देश्य को नहीं हराता है? मैं एसक्यूएल का उपयोग करना चाहता हूं। यह इसे अमूर्त करता है। मैं क्या खो रहा हूँ?
जॉनी

2
@ जॉनी यह सिर्फ सहायक वर्ग है ... कुछ लोग चाहते हैं कि उनका कोड जितना संभव हो सके ... आपको इसका उपयोग नहीं करना है यदि आप इसे नहीं चाहते हैं।
रोजी कासिम

68

डैपर का उपयोग करके CRUD ऑपरेशन करना एक आसान काम है। मैंने नीचे दिए गए उदाहरणों का उल्लेख किया है जो आपको CRUD संचालन में मदद करनी चाहिए।

C RUD के लिए कोड :

विधि # 1: इस पद्धति का उपयोग तब किया जाता है जब आप विभिन्न संस्थाओं से मान डाल रहे होते हैं।

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string insertQuery = @"INSERT INTO [dbo].[Customer]([FirstName], [LastName], [State], [City], [IsActive], [CreatedOn]) VALUES (@FirstName, @LastName, @State, @City, @IsActive, @CreatedOn)";

    var result = db.Execute(insertQuery, new
    {
        customerModel.FirstName,
        customerModel.LastName,
        StateModel.State,
        CityModel.City,
        isActive,
        CreatedOn = DateTime.Now
    });
}

विधि # 2: इस विधि का उपयोग तब किया जाता है जब आपकी इकाई गुणों में SQL कॉलम के समान नाम होते हैं। तो, Dapper ORM मैप्स एंटिटी प्रॉपर्टीज के साथ मेल खाता SQL कॉलम है।

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string insertQuery = @"INSERT INTO [dbo].[Customer]([FirstName], [LastName], [State], [City], [IsActive], [CreatedOn]) VALUES (@FirstName, @LastName, @State, @City, @IsActive, @CreatedOn)";

    var result = db.Execute(insertQuery, customerViewModel);
}

सी आर यूडी के लिए कोड :

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string selectQuery = @"SELECT * FROM [dbo].[Customer] WHERE FirstName = @FirstName";

    var result = db.Query(selectQuery, new
    {
        customerModel.FirstName
    });
}

सीआर यू डी के लिए कोड :

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string updateQuery = @"UPDATE [dbo].[Customer] SET IsActive = @IsActive WHERE FirstName = @FirstName AND LastName = @LastName";

    var result = db.Execute(updateQuery, new
    {
        isActive,
        customerModel.FirstName,
        customerModel.LastName
    });
}

CRU D के लिए कोड :

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string deleteQuery = @"DELETE FROM [dbo].[Customer] WHERE FirstName = @FirstName AND LastName = @LastName";

    var result = db.Execute(deleteQuery, new
    {
        customerModel.FirstName,
        customerModel.LastName
    });
}

26

आप इसे इस तरह से कर सकते हैं:

sqlConnection.Open();

string sqlQuery = "INSERT INTO [dbo].[Customer]([FirstName],[LastName],[Address],[City]) VALUES (@FirstName,@LastName,@Address,@City)";
sqlConnection.Execute(sqlQuery,
    new
    {
        customerEntity.FirstName,
        customerEntity.LastName,
        customerEntity.Address,
        customerEntity.City
    });

sqlConnection.Close();

36
आपको इसका उपयोग करना चाहिए using-statementताकि अपवाद के मामले में भी कनेक्शन बंद हो जाए।
टिम श्मेल्टर

12
आप केवल गुमनाम प्रकार का उपयोग करने के बजाय सीधे ग्राहक पास कर सकते हैं ...
थॉमस लेवेस्क

@ThomasLevesque इसका क्या मतलब है? क्या आप अपने मतलब के छोटे कोड का उदाहरण दे सकते हैं?
ियाकप '

4
@ आईएसीसीपी, मेरा मतलब है कि:sqlConnection.Execute(sqlQuery, customerEntity);
थॉमस लेवेस्क

1
@ThomasLevesque क्या हम उसी पैटर्न का उपयोग करके भी अपडेट कर सकते हैं? यानी,sqlConnection.Execute(sqlQuery, customerEntity);
शंकर

16

Dapper.Cribrib का उपयोग करना इस रूप में सरल है:

सूची सम्मिलित करें:

public int Insert(IEnumerable<YourClass> yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Insert(yourClass) ;
    }
}

एकल डालें:

public int Insert(YourClass yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Insert(yourClass) ;
    }
}

अद्यतन सूची:

public bool Update(IEnumerable<YourClass> yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Update(yourClass) ;
    }
}

एकल अपडेट करें:

public bool Update(YourClass yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Update(yourClass) ;
    }
}

स्रोत: https://github.com/StackExchange/Dapper/tree/master/Dapper.Contrib


1
किसी एकल ऑब्जेक्ट को सम्मिलित करने के लिए उपरोक्त का उपयोग करके आप नई पहचान संख्या वापस प्राप्त कर सकते हैं और इसे वापस अपने मॉडल में डाल सकते हैं ... लेकिन आप इसे ऑब्जेक्ट्स की सूची सम्मिलित करने के लिए कैसे करते हैं - सूची में ऑब्जेक्ट्स नहीं हैं पहचान क्षेत्र। क्या आपको सूची के माध्यम से पुनरावृत्त करना है और फिर उन्हें एक बार सम्मिलित करना है, हर बार नई आईडी प्राप्त करना है?
हरग

1
@ अगर आपको नई आईडी की आवश्यकता है तो कहीं और मुझे लगता है कि आपको ऐसा करना होगा। एंटिटी फ्रेमवर्क संदर्भ प्रकारों को संभालता है, वर्गों की तरह, आवेषण के साथ एक समस्या के बिना, लेकिन मुझे नहीं पता कि डैपर.कंट्रिब कैसे उसके साथ काम करता है यदि वह आपका कोण था।
ओग्लास

5
@ ऑग्लास, धन्यवाद। मैंने देखा है कि "कनेक्शन। इनओटर (myObject)" "myObject" की "[कुंजी]" संपत्ति को अपडेट करेगा यदि मैं सिर्फ एक ऑब्जेक्ट डाल रहा हूं, लेकिन अगर मैं 5 ऑब्जेक्ट्स की सूची सम्मिलित कर रहा हूं तो उसी का उपयोग करके "connection.Insert (myObjectList)" तब कोई भी [कुंजी] गुण अपडेट नहीं किए जाते हैं, इसलिए मुझे सूची में मैन्युअल रूप से आइटम निकालने और उन्हें एक बार में सम्मिलित करना होगा।
हरग

1
में conn.Update(yourClass)अगर कुछ गुण अशक्त हैं , तो शून्य करने के लिए फ़ील्ड अपडेट ? काम नहीं कर रहा। फ़ील्ड को NULL में अपडेट करेंNot partials updates
किकेनीत

5

आप एक संग्रहीत कार्यविधि और सामान्य तरीके से डापर का उपयोग भी कर सकते हैं जिसके द्वारा सब कुछ आसानी से प्रबंधित किया जा सकता है।

अपना कनेक्शन परिभाषित करें:

public class Connection: IDisposable
{
    private static SqlConnectionStringBuilder ConnectionString(string dbName)
    {
        return new SqlConnectionStringBuilder
            {
                ApplicationName = "Apllication Name",
                DataSource = @"Your source",
                IntegratedSecurity = false,
                InitialCatalog = Database Name,
                Password = "Your Password",
                PersistSecurityInfo = false,
                UserID = "User Id",
                Pooling = true
            };
    }

    protected static IDbConnection LiveConnection(string dbName)
    {
        var connection = OpenConnection(ConnectionString(dbName));
        connection.Open();
        return connection;
    }

    private static IDbConnection OpenConnection(DbConnectionStringBuilder connectionString)
    {
        return new SqlConnection(connectionString.ConnectionString);
    }

    protected static bool CloseConnection(IDbConnection connection)
    {
        if (connection.State != ConnectionState.Closed)
        {
            connection.Close();
            // connection.Dispose();
        }
        return true;
    }

    private static void ClearPool()
    {
        SqlConnection.ClearAllPools();
    }

    public void Dispose()
    {
        ClearPool();
    }
}

Dapper विधियों को परिभाषित करने के लिए एक इंटरफ़ेस बनाएँ, जिनकी आपको वास्तव में आवश्यकता है:

 public interface IDatabaseHub
    {
   long Execute<TModel>(string storedProcedureName, TModel model, string dbName);

        /// <summary>
        /// This method is used to execute the stored procedures with parameter.This is the generic version of the method.
        /// </summary>
        /// <param name="storedProcedureName">This is the type of POCO class that will be returned. For more info, refer to https://msdn.microsoft.com/en-us/library/vstudio/dd456872(v=vs.100).aspx. </param>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="model">The model object containing all the values that passes as Stored Procedure's parameter.</param>
        /// <returns>Returns how many rows have been affected.</returns>
        Task<long> ExecuteAsync<TModel>(string storedProcedureName, TModel model, string dbName);

        /// <summary>
        /// This method is used to execute the stored procedures with parameter. This is the generic version of the method.
        /// </summary>
        /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
        /// <param name="parameters">Parameter required for executing Stored Procedure.</param>        
        /// <returns>Returns how many rows have been affected.</returns>         
        long Execute(string storedProcedureName, DynamicParameters parameters, string dbName);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="storedProcedureName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        Task<long> ExecuteAsync(string storedProcedureName, DynamicParameters parameters, string dbName);
}

इंटरफ़ेस लागू करें:

     public class DatabaseHub : Connection, IDatabaseHub
        {

 /// <summary>
        /// This function is used for validating if the Stored Procedure's name is correct.
        /// </summary>
        /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
        /// <returns>Returns true if name is not empty and matches naming patter, otherwise returns false.</returns>

        private static bool IsStoredProcedureNameCorrect(string storedProcedureName)
        {
            if (string.IsNullOrEmpty(storedProcedureName))
            {
                return false;
            }

            if (storedProcedureName.StartsWith("[") && storedProcedureName.EndsWith("]"))
            {
                return Regex.IsMatch(storedProcedureName,
                    @"^[\[]{1}[A-Za-z0-9_]+[\]]{1}[\.]{1}[\[]{1}[A-Za-z0-9_]+[\]]{1}$");
            }
            return Regex.IsMatch(storedProcedureName, @"^[A-Za-z0-9]+[\.]{1}[A-Za-z0-9]+$");
        }

     /// <summary>
            /// This method is used to execute the stored procedures without parameter.
            /// </summary>
            /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
            /// <param name="model">The model object containing all the values that passes as Stored Procedure's parameter.</param>
            /// <typeparam name="TModel">This is the type of POCO class that will be returned. For more info, refer to https://msdn.microsoft.com/en-us/library/vstudio/dd456872(v=vs.100).aspx. </typeparam>
            /// <returns>Returns how many rows have been affected.</returns>

            public long Execute<TModel>(string storedProcedureName, TModel model, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return connection.Execute(
                            sql: storedProcedureName,
                            param: model,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );

                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }

            public async Task<long> ExecuteAsync<TModel>(string storedProcedureName, TModel model, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return await connection.ExecuteAsync(
                            sql: storedProcedureName,
                            param: model,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );

                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }

            /// <summary>
            /// This method is used to execute the stored procedures with parameter. This is the generic version of the method.
            /// </summary>
            /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
            /// <param name="parameters">Parameter required for executing Stored Procedure.</param>        
            /// <returns>Returns how many rows have been affected.</returns>

            public long Execute(string storedProcedureName, DynamicParameters parameters, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return connection.Execute(
                            sql: storedProcedureName,
                            param: parameters,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }



            public async Task<long> ExecuteAsync(string storedProcedureName, DynamicParameters parameters, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return await connection.ExecuteAsync(
                            sql: storedProcedureName,
                            param: parameters,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );

                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }

    }

अब आप अपनी आवश्यकता के अनुसार मॉडल से कॉल कर सकते हैं:

public class DeviceDriverModel : Base
    {
 public class DeviceDriverSaveUpdate
        {
            public string DeviceVehicleId { get; set; }
            public string DeviceId { get; set; }
            public string DriverId { get; set; }
            public string PhoneNo { get; set; }
            public bool IsActive { get; set; }
            public string UserId { get; set; }
            public string HostIP { get; set; }
        }


        public Task<long> DeviceDriver_SaveUpdate(DeviceDriverSaveUpdate obj)
        {

            return DatabaseHub.ExecuteAsync(
                    storedProcedureName: "[dbo].[sp_SaveUpdate_DeviceDriver]", model: obj, dbName: AMSDB);//Database name defined in Base Class.
        }
}

आप मापदंडों को भी पास कर सकते हैं:

public Task<long> DeleteFuelPriceEntryByID(string FuelPriceId, string UserId)
        {


            var parameters = new DynamicParameters();
            parameters.Add(name: "@FuelPriceId", value: FuelPriceId, dbType: DbType.Int32, direction: ParameterDirection.Input);
            parameters.Add(name: "@UserId", value: UserId, dbType: DbType.String, direction: ParameterDirection.Input);

            return DatabaseHub.ExecuteAsync(
                    storedProcedureName: @"[dbo].[sp_Delete_FuelPriceEntryByID]", parameters: parameters, dbName: AMSDB);

        }

अब अपने नियंत्रकों से कॉल करें:

var queryData = new DeviceDriverModel().DeviceInfo_Save(obj);

आशा है कि यह आपके कोड की पुनरावृत्ति को रोकने और सुरक्षा प्रदान करेगा;



0

क्वेरी संचालन के लिए किसी भी 3 पार्टी लाइब्रेरी का उपयोग करने के बजाय, मैं आपको स्वयं प्रश्न लिखना चाहूंगा। क्योंकि किसी भी अन्य तीसरे पक्ष के पैकेज का उपयोग करने से प्रश्नों को लिखने के लिए डैपर यानी लचीलेपन का उपयोग करने का मुख्य लाभ होगा।

अब, संपूर्ण ऑब्जेक्ट के लिए इन्सर्ट या अपडेट क्वेरी लिखने में समस्या है। इसके लिए, कोई भी मददगार नीचे की तरह बना सकता है:

InsertQueryBuilder:

 public static string InsertQueryBuilder(IEnumerable < string > fields) {


  StringBuilder columns = new StringBuilder();
  StringBuilder values = new StringBuilder();


  foreach(string columnName in fields) {
   columns.Append($ "{columnName}, ");
   values.Append($ "@{columnName}, ");

  }
  string insertQuery = $ "({ columns.ToString().TrimEnd(',', ' ')}) VALUES ({ values.ToString().TrimEnd(',', ' ')}) ";

  return insertQuery;
 }

अब, सम्मिलित करने के लिए कॉलम के नाम को पास करके, पूरी क्वेरी स्वचालित रूप से बनाई जाएगी, जैसे नीचे:

List < string > columns = new List < string > {
 "UserName",
 "City"
}
//QueryBuilder is the class having the InsertQueryBuilder()
string insertQueryValues = QueryBuilderUtil.InsertQueryBuilder(columns);

string insertQuery = $ "INSERT INTO UserDetails {insertQueryValues} RETURNING UserId";

Guid insertedId = await _connection.ExecuteScalarAsync < Guid > (insertQuery, userObj);

आप तालिका नाम पैरामीटर को पारित करके पूरे INSERT विवरणी को वापस करने के लिए फ़ंक्शन को भी संशोधित कर सकते हैं।

सुनिश्चित करें कि वर्ग गुण नाम डेटाबेस में फ़ील्ड नामों के साथ मेल खाता है। तब केवल आप ही पूरे ओब्ज को पास कर सकते हैं (जैसे हमारे मामले में userObj) और मानों को स्वचालित रूप से मैप किया जाएगा।

उसी तरह, आप UPDATE क्वेरी के लिए सहायक फ़ंक्शन भी कर सकते हैं:

  public static string UpdateQueryBuilder(List < string > fields) {
   StringBuilder updateQueryBuilder = new StringBuilder();

   foreach(string columnName in fields) {
    updateQueryBuilder.AppendFormat("{0}=@{0}, ", columnName);
   }
   return updateQueryBuilder.ToString().TrimEnd(',', ' ');
  }

और इसका उपयोग करें:

List < string > columns = new List < string > {
 "UserName",
 "City"
}
//QueryBuilder is the class having the UpdateQueryBuilder()
string updateQueryValues = QueryBuilderUtil.UpdateQueryBuilder(columns);

string updateQuery =  $"UPDATE UserDetails SET {updateQueryValues} WHERE UserId=@UserId";

await _connection.ExecuteAsync(updateQuery, userObj);

यद्यपि इन सहायक कार्यों में भी, आपको उन फ़ील्ड्स का नाम पास करना होगा जिन्हें आप सम्मिलित करना चाहते हैं या अपडेट करना चाहते हैं लेकिन कम से कम आपके पास क्वेरी पर पूर्ण नियंत्रण है और आवश्यकता पड़ने पर अलग-अलग WHERE क्लॉस भी शामिल कर सकते हैं।

इस सहायक कार्यों के माध्यम से, आप कोड की निम्नलिखित पंक्तियों को सहेजेंगे:

सम्मिलित प्रश्न के लिए:

 $ "INSERT INTO UserDetails (UserName,City) VALUES (@UserName,@City) RETURNING UserId";

अपडेट क्वेरी के लिए:

$"UPDATE UserDetails SET UserName=@UserName, City=@City WHERE UserId=@UserId";

कोड की कुछ पंक्तियों में अंतर प्रतीत होता है, लेकिन जब 10 से अधिक फ़ील्ड वाली तालिका के साथ इन्सर्ट या अपडेट ऑपरेशन करने की बात आती है, तो कोई अंतर महसूस कर सकता है।

आप टाइपो से बचने के लिए फ़ंक्शन में फ़ील्ड नाम को पास करने के लिए नेमॉफ़ ऑपरेटर का उपयोग कर सकते हैं

के बजाय:

List < string > columns = new List < string > {
 "UserName",
 "City"
}

तुम लिख सकते हो:

List < string > columns = new List < string > {
nameof(UserEntity.UserName),
nameof(UserEntity.City),
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.