Linq to Entities和POCO外键关系映射(1到0..1)问题

时间:2010-04-14 04:58:25

标签: asp.net-mvc linq entity-framework linq-to-entities

对于我的ASP.NET MVC 2应用程序,我使用Entity Framework 1.0作为我的数据访问层(存储库)。但我决定要回归POCO。当我想要获得带有可选徽标的品牌列表时,我第一次遇到问题。这是我做的:

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类中使用nullable但这不自然 - 然后我不仅要检查我的服务层或控制器和视图中Logo是否为空,而且主要是Logo.ImageId.HasValue。如果ID为null,则拥有非Logo null属性是不合理的。

有人能想到更好的解决方案吗?

3 个答案:

答案 0 :(得分: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;
}

我想它比方形选择品牌Xlogos更好,而不是我建议使用JOIN 如果您觉得有用,请告诉我们

答案 1 :(得分:0)

一种选择是首先不允许数据库中的空标识,并且在数据库中具有特殊标识id = 0,即无标识徽标。把它放在没有徽标的任何品牌上。即空值模式。

如果您不喜欢使用硬编码ID,请在徽标上创建一个位值“IsNullLogo”,并使用它来初步查找徽标ID(因为它可能在生产中具有不同的ID以进行开发......)

答案 2 :(得分:0)

我有另一个解决方法。因为在某些情况下,Image(Logo属性的类)不能是null,在某些情况下,我可以决定将一些继承添加到我的Image模型中。这就是我所做的:

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;
    }
}

然后我的存储库返回一个可空的Id,仅用于与Image有0..1关系的对象 - 比如Brand。但是具有必需DefaultImage属性的Product将使用不带nullable 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数据库的值不能为空,它将正常工作,一切都将是自然的控制器和视图。 我认为这种解决方法非常适合我的需求。如果有人有更好的解决方案,请随时回复。