我對Entity Framework完全陌生。我創建了一個模型來觀看遠程機器上的服務。目前看起來是這樣的:實體框架代碼首先在內部使用虛擬屬性,當調用時爲空引用
注意:我已盡力使用可理解的通用名稱,因爲這是來自企業環境。
public class RemoteService
{
[Key, Column(Order = 0)]
public string Name { get; set; }
[Key, Column(Order = 1)]
public string MachineName { get; set; }
[ForeignKey("MachineName")]
public virtual RemoteEnvironment RunningAt { get; set; }
}
public class RemoteEnvironment
{
[Key]
public string MachineName { get; set; }
public string Configuration { get; set; }
public string EnvironmentNr { get; set; }
public virtual ICollection<RemoteService> Services { get; set; }
}
隨着上下文類:創建數據庫和它播種時
public class MyDBContext : DbContext
{
public DbSet<RemoteEnvironment> RemoteEnvironments { get; set; }
public DbSet<RemoteService> RemoteServices { get; set; }
}
這個優良樣板工程。 RemoteService
類還包含此Version
屬性,以從Octopus Deploy API獲取版本。
private string _version = "N/A";
public string Version
{
get
{
var item = GetItemFromOctopus(Name, RunningAt.EnvironmentNr);
if (item != null)
{
_version = item.ReleaseVersion;
}
return _version;
}
set
{
}
}
這也適用於創建和種子數據庫。我試圖從數據庫中獲取數據時出現我的問題。事情是這樣的:
using (MyDBContext context = new MyDBContext())
{
var serviceNames = new List<string>();
foreach (RemoteService service in context.RemoteServices)
{
serviceNames.Add(service.Name);
}
}
在執行上面的代碼中,我得到一個NullReferenceException
,因爲RunningAt
爲空。
調試從我收集,這是當我搶service
從context.RemoteServices
,它獲取的所有屬性。首先Name
,然後MachineName
,跳過RunningAt
(爲什麼?懶加載?)然後試圖得到Version
,但由於RunningAt
爲空,它不能。
我試圖定義RunningAt
get和使用
private RemoteEnvironment _runningAt
設置方法,但問題保持不變,兩者RunningAt
和_runningAt
都爲空,而從數據庫中提取數據。
看來我不知何故需要從Version
的數據庫中加載對RemoteEnvironment
的引用。但是,在這裏創建一個上下文似乎有點多。
我還能做什麼?我真的想保持Version
原樣。如果無法完成,我將不得不採取一種解決方法。單獨檢查版本,反而積極獲取並設置它。
編輯1: 我現在已經嘗試了三種不同的方式爲「預加載」的RemoteEnvironments
。
第一張: 從數據庫中獲取所有RemoteEnvironments
的「預加載」。
using (MyDBContext context = new MyDBContext())
{
var serviceNames = new List<string>();
List<M3BEnvironment> activateEnv = db.M3BEnvvironments.ToList(); //added line
foreach (RemoteService service in context.RemoteServices)
{
serviceNames.Add(service.Name);
}
}
仍然得到NullReferenceException,因爲RunningAt爲null。
第二個: 刪除虛擬關鍵字。
[ForeignKey("MachineName")]
public RemoteEnvironment RunningAt { get; set; } // virtual keyword removed
仍然收到NullReferenceException,因爲RunningAt爲空。
第三: 使用Include
強制加載。
using (MyDBContext context = new MyDBContext())
{
var serviceNames = new List<string>();
var services = context.RemoteServices.Include(s => s.RunningAt).ToList();
foreach (RemoteService service in services)
{
serviceNames.Add(service.Name);
}
}
仍然得到NullReferenceException,因爲RunningAt爲null。
我甚至嘗試了上述的所有組合,包括所有三個在同一時間。 由於RunningAt爲null,所以仍然得到NullReferenceException。
我也試着走另一條路,通過RemoteEnvironments
和包括Services
:
using (MyDBContext context = new MyDBContext())
{
var environments = context.RemoteEnvironments.Include(env => env.Services).ToList(); // NullRefereceException happens at this call
var serviceNames = new List<string>();
var services = context.RemoteServices.Include(s => s.RunningAt).ToList();
foreach (RemoteService service in services)
{
serviceNames.Add(service.Name);
}
}
仍然得到的NullReferenceException因爲RunningAt爲空。只有這一次它發生,而environments
電話試圖包括他們。
我想要做的事似乎不可能。使用Version
屬性中引用的RunningAt
屬性,因爲它永遠不會從數據庫加載。即使我強迫它在呼叫RemoteService
之前加載RemoteEnvironments
,並隨後呼叫Version
。
因爲'RunningAt'在'context.RemoteEnvironments'而不是'context.RemoteServices'你試圖從中獲得它我猜 – jamiedanq
@jamiedanq嗯,是的。這是當前的問題。我希望能夠在'Version'屬性中引用它。最好不必創建新的數據庫引用。我考慮的越多,就越傾向於尋找解決方法。 – Skillzore
爲什麼不在獲取版本之前先從數據庫中獲取所有'RemoteEnvironments'? – jamiedanq