2010-04-14 22 views
0

對於我的ASP.NET MVC 2應用程序,我使用Entity Framework 1.0作爲我的數據訪問層(存儲庫)。但我決定我想要返回POCO。我第一次遇到一個問題,當我想要通過他們的可選標識獲得品牌列表時。以下是我所做的:Linq to Entities和POCO外鍵關係映射(1到0..1)問題

public IQueryable<Model.Products.Brand> GetAll() 
    { 
     IQueryable<Model.Products.Brand> brands = from b in EntitiesCtx.Brands.Include("Logo") 
                select new Model.Products.Brand() 
                 { 
                  BrandId = b.BrandId, 
                  Name = b.Name, 
                  Description = b.Description, 
                  IsActive = b.IsActive, 
                  Logo = /*b.Logo != null ? */new Model.Cms.Image() 
                    { 
                     ImageId = b.Logo.ImageId, 
                     Alt = b.Logo.Alt, 
                     Url = b.Logo.Url 
                    }/* : null*/ 
                 }; 
     return brands; 
    } 

您可以在評論中看到我想達到的目標。它工作得很好,只要BrandLogo,否則它通過一個例外,你可以將null分配給非空類型int(對於Id)。我的解決方法是在POCO類中使用空值,但這不是自然的 - 那麼我不僅要檢查Logo是否在我的服務層或控制器和視圖中爲空,而且大多數爲Logo.ImageId.HasValue。如果ID爲null,那麼擁有非nullLogo屬性是沒有理由的。

任何人都可以想到更好的解決方案嗎?

+2

如果Logo無效且ImageId爲空,那麼這將表明您的基礎數據庫存在問題。如果您的EF ORM將Logo對象的ImageId屬性映射到Nullable ,這可能是因爲數據庫中的列接受空值,但如果它是關鍵字段,則不應接受空值。 – jeffora 2010-04-14 05:43:43

回答

0

我對此有另一種解決方法。因爲在某些情況下,圖像(徽標屬性的類)不能是null,並且在某些情況下,我可以決定向圖像的模型中添加一些繼承。下面是我做了什麼:

public class OptionalImage 
{ 
    public long? ImageId 
    { 
     get; 
     set; 
    } 

    [DisplayName("Obraz")] 
    [StringLength(200, ErrorMessage = "Url jest za długi")] 
    [RegularExpression(@".*\.(jpg|gif|png|jpeg|tif|tiff|JPG|GIF|PNG|JPEG|TIF|TIFF)$", ErrorMessage = "Rozszerzenie pliku jest nieprawidłowe. Dopuszczone to: .jpg, .gif, .png, .jpeg, .tif, .tiff")] 
    public string Url 
    { 
     get; 
     set; 
    } 

    [StringLength(200, ErrorMessage = "Tekst alternatywny jest za długi")] 
    [DisplayName("Tekst alternatywny")] 
    public string Alt 
    { 
     get; 
     set; 
    } 
} 

public class Image : OptionalImage 
{ 
    public new long ImageId 
    { 
     get; 
     set; 
    } 
} 

然後我的倉庫只適用於具有圖像0..1關係的對象返回null的標識 - 就像品牌。但是具有必需的DefaultImage屬性的產品將使用與數據庫和業務邏輯設計相對應的沒有可爲空的Id的Image。

資源庫中的GetAll方法現在看起來是這樣的(感謝@omoto的提示):

public IQueryable<Model.Products.Brand> GetAll() 
    { 
     IQueryable<Model.Products.Brand> brands = from b in EntitiesCtx.Brands 
                let logo = EntitiesCtx.Images.FirstOrDefault(c => c.ImageId == b.Logo.ImageId) 
                select new Model.Products.Brand() 
                 { 
                  BrandId = b.BrandId, 
                  Name = b.Name, 
                  Description = b.Description, 
                  IsActive = b.IsActive, 
                  Logo = new Model.Cms.OptionalImage() 
                    { 
                     ImageId = logo.ImageId, 
                     Alt = logo.Alt, 
                     Url = logo.Url 
                    } 
                 }; 
     return brands; 
    } 

對於產品代替new Model.Cms.OptionalImage()我會用new Model.Cms.Image(),並因爲在這種情況下提出的ImageId數據庫的價值不能爲null,它會正常工作,一切都將在控制器和視圖中自然。 我認爲這種解決方法非常適合我的需求。如果有人有更好的解決方案,請隨時回覆。

1

只是一個選項

public IQueryable<Model.Products.Brand> GetAll() 
{ 
    IQueryable<Model.Products.Brand> brands = from b in EntitiesCtx.Brands 
               let logo =EntitiesCtx.Logos.First(c=>c.LogoId==b.LogoId); 
               select new Model.Products.Brand() 
                { 
                 BrandId = b.BrandId, 
                 Name = b.Name, 
                 Description = b.Description, 
                 IsActive = b.IsActive, 
                 Logo = /*b.Logo != null ? */new Model.Cms.Image() 
                   { 
                    ImageId = logo.ImageId, 
                    Alt = logo.Alt, 
                    Url = logo.Url 
                   }/* : null*/ 
                }; 
    return brands; 
} 

我想這是比方選擇brandsXlogos,而不是這個,我建議使用JOIN 讓我知道,請你是否會有所幫助

+0

感謝您的建議 - 它確實比硬編碼Logo屬性的導航字符串要好。 – 2010-04-14 05:40:20

0

一個選項將首先不要在數據庫中允許空徽標,並且在沒有徽標徽標的數據庫中使用特殊徽標id = 0。把它放在你沒有標識的品牌上。即空值模式。

如果你不喜歡硬編碼的ID,創建標誌位值「IsNullLogo」,並用它來找到最初的標識ID(因爲它可能有不同的ID在生產發展... )。

+0

那麼,如果我不允許我的數據庫中的徽標爲Logo,那麼如果我插入0我將違反外鍵約束,因爲沒有該圖像與該ID。而爲這種情況添加和ID爲0的圖像絕對不是一個好的解決方案。想想讓用戶管理圖像。如果他們不試圖刪除或更新我的冬青1號,我將不得不到處檢查。事情變得麻煩。 – 2010-04-14 08:28:55

+0

您在數據庫中有特殊的系統徽標,因此沒有違規行爲。你不要讓用戶操縱這個特殊的圖像(或任何其他特殊的系統圖像)。這既不罕見也不難。 – 2010-04-14 15:28:03

+0

我知道這是一個常見的解決方案,它在許多情況下是合理的。對於我來說,檢查空值是比擁有特殊的數據庫記錄更自然。爲什麼我會需要這個記錄而不是檢查品牌(或產品或其他)是否沒有徽標?爲此,我不認爲這是一個在DB中有特殊記錄的好方法。如果我想爲沒有徽標的品牌使用默認圖像,那麼我希望在表示層中使用這些徽標,而不是數據庫。所以我仍然希望檢查null。 – 2010-04-15 07:17:50