2013-03-06 24 views
0

當我運行我的代碼時,它告訴我adr的對象爲空,而且這是真的,但爲什麼在它工作在相同方法的副本中時不工作,插入的替代而不是選擇。將不會接受C#中的空對象

的代碼如下所示:

public City doesExist(string postnr, string navn, City city, SqlConnection con) 
{ 
    DatabaseConnection.openConnection(con); 
    using (var command = new SqlCommand("select Id from [By] where Postnummer='" + postnr + "' and Navn='" + navn + "'", con)) 
    { 
     command.Connection = con; 
     SqlDataReader reader = command.ExecuteReader(); 
     if (reader.Read()) 
     { 
      city.id = reader.GetInt32(0); 
      city.postnr = postnr; 
      city.navn = navn; 
      reader.Close(); 

      return city; 
     } 

     reader.Close(); 
     return null; 
    } 
} 

public City create(string postnr, string navn, City city, SqlConnection con) 
{ 
    DatabaseConnection.openConnection(con); 
    using (var command = new SqlCommand("insert into [By] (Postnummer, Navn) values ('" + postnr + "', '" + navn + "'); select @@identity as 'identity';", con)) 
    { 
     object ID = command.ExecuteScalar(); 

     city.id = Convert.ToInt32(ID); 
     city.postnr = postnr; 
     city.navn = navn; 
     return city; 
    } 
} 

調用看起來是這樣的:

City city = new City(); 
city = city.doesExist(zip, by, city, connection); // this works fine 
if (city == null) 
{ 
    // I know that city is null 
    // tried inserting City city = new City(); same error 
    city = city.create(zip, by, city, connection); // this is where the null error occours 
} 
+3

爲什麼'create'方法是'City'類的實例方法?當然它會拋出異常。畢竟,「城市」是空的,不是嗎? – Groo 2013-03-06 13:28:51

+0

不是'創建'方法需要'靜態'嗎? – Arran 2013-03-06 13:29:15

+0

請注意,您的'doesExist'方法還會輸入未使用的輸入'city'參數,應該將其刪除。實際上,這兩種方法看起來都像存儲庫方法,即它們不應該是城市類的**實例**方法(因爲它們不屬於單個城市實例)。 – Groo 2013-03-06 13:31:29

回答

8

嗯,是的,看看:

if (city == null) 
{ 
    // If we've got in here, we know that city is a null reference, but... 
    city = city.create(...); 
} 

你調用一個方法參考其中絕對是 null。這保證會拋出NullReferenceException

幾乎可以確定你想要讓你的create方法靜態的(並重新命名它符合正常的.NET命名約定),並把它作爲

city = City.Create(...); 

您還需要刪除從city參數方法調用,而是在內部創建一個新的City對象您的方法。例如:

public static City Create(string postnr, string navn, SqlConnection con) 
{ 
    DatabaseConnection.openConnection(con); 
    using (var command = new SqlCommand 
     ("insert into [By] (Postnummer, Navn) values (@postnr, @navn); "+ 
      "select @@identity as 'identity';", con)) 
    { 
     command.Parameters.Add("@postnr", SqlDbType.NVarChar).Value = postnr; 
     command.Parameters.Add("@navn", SqlDbType.NVarChar).Value = navn; 
     object ID = command.ExecuteScalar(); 

     City = new City(); 
     city.id = Convert.ToInt32(ID); 
     city.postnr = postnr; 
     city.navn = navn; 
     return city; 
    } 
} 

請注意我是如何更改代碼以使用參數化SQL的。你真的,不應該把值直接放入你的SQL語句中 - 它會打開你的系統到SQL injection attacks,並使各種轉換混亂。

此外,我建議爲每個數據庫操作創建一個新的SqlConnection(並關閉它)。

坦率地說,doesExist也是一個實例方法,有點奇怪,而且它也需要參數city

我建議改變這個設計,讓您有一個CityRepository(或類似的東西),它知道連接字符串,並公開:

// I'd rename these parameters to be more meaningful, but as I can't work out what they're 
// meant to mean now, it's hard to suggest alternatives. 
public City Lookup(string postnr, string nav) 

public City Create(string postnr, string nav) 

版本庫會知道相關的連接字符串,並會負責所有的數據庫操作。 City類型對數據庫一無所知。

+1

...並可能從方法中刪除'city'參數。 – Groo 2013-03-06 13:30:35

+0

@格羅:確實。將編輯。 – 2013-03-06 13:31:08

+1

+1:用於同時刪除Sql注入漏洞。 – RBarryYoung 2013-03-06 13:39:44

0

您正嘗試調用尚未初始化的對象類的方法/爲空。

您需要將City.create設爲靜態成員。

public static City create(string postnr, string navn, City city, SqlConnection con) 
{ 
    DatabaseConnection.openConnection(con); 
    using (var command = new SqlCommand("insert into [By] (Postnummer, Navn) values ('" + postnr + "', '" + navn + "'); select @@identity as 'identity';", con)) 
    { 
     object ID = command.ExecuteScalar(); 

     city.id = Convert.ToInt32(ID); 
     city.postnr = postnr; 
     city.navn = navn; 
     return city; 
    } 
} 

而且使用它像:

if(city==null) 
{ 
    City city = City.create(...); 
} 
0

更好的辦法:

static public City create(string postnr, string navn, SqlConnection con) 
{ 
    DatabaseConnection.openConnection(con); 
    using (var command = new SqlCommand("insert into [By] (Postnummer, Navn) values ('" + postnr + "', '" + navn + "'); select @@identity as 'identity';", con)) 
    { 
     object ID = command.ExecuteScalar(); 

     City city = new City(); 
     city.id = Convert.ToInt32(ID); 
     city.postnr = postnr; 
     city.navn = navn; 
     return city; 
    } 

    return null; 
} 

創建方法必須是靜態的,沒有必要有城市的說法。 呼叫:

if (city == null) 
{ 
     city = City.Create(.....); 
} 
+1

太晚了......再次^^ – Xaruth 2013-03-06 13:37:41

相關問題