【问题标题】:EF 5 derived classes can't access partial class's propertyEF 5 派生类无法访问部分类的属性
【发布时间】:2013-01-16 21:48:07
【问题描述】:

我有一个 EF 5/MVC 4,我正在处理的数据库优先项目,并为我的应用程序的某些逻辑功能区域(UserManagement、CompanyManagement、InventoryManagement、OrderManagement)创建了单独的 edmx 文件。 UserProfile 表位于所有 edmx 文件中,因为它可以加入 CreatedById 和 ModifiedById 表,因此您可以获得实际的用户名。但我不想在 UserProfile 表的每个版本中创建额外的属性和数据注释,所以我继承了 UserProfile 的(我称之为)“原始版本”,它位于 UserManagement 区域中,我添加了我的额外属性并添加我的数据注释。好的,还和我在一起吗?

好的,这是 EF 5 创建的原始 UserProfile 类(在 UserManagement 区域/文件夹中):

namespace OTIS.domain.UserMgmt
{
    using System;
    using System.Collections.Generic;

    public partial class UserProfile
    {
        public UserProfile()
        {
            this.webpages_Roles = new HashSet<webpages_Roles>();
        }

        public int UserId { get; set; }
        public Nullable<int> AccountId { get; set; }
        public string UserName { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }

        public virtual webpages_Membership webpages_Membership { get; set; }
        public virtual ICollection<webpages_Roles> webpages_Roles { get; set; }
    }
}

这是我用来添加其他属性和添加数据注释的部分类:

namespace OTIS.domain.UserMgmt
{
    [MetadataType(typeof(UserProfileMD))]
    public partial class UserProfile : IEntity
    {
        public int Id
        {
            get
            {
                return this.UserId;
            }
        }

        public string FullName
        {
            get
            {
                return this.FirstName + " " + this.LastName;
            }
        }

        public string EntityDescription
        {
            get
            {
                return this.FullName;
            }
        }

        public class UserProfileMD
        {
            public int UserId { get; set; }

            [Required]
            [Display(Name = "User Name")]
            public string UserName { get; set; }

            [Required]
            [Display(Name = "First Name")]
            public string FirstName { get; set; }

            [Required]
            [Display(Name = "Last Name")]
            public string LastName { get; set; }

            [Display(Name = "Name")]
            public string FullName { get; set; }

            [Display(Name = "Email")]
            public string Email { get; set; }

        }
    }
}

现在我正在使用 InventoryMgmt edmx 中的 UserProfile 版本,因此我创建了一个同名的部分类并从上面继承:

namespace OTIS.domain.InventoryMgmt
{
    [MetadataType(typeof(OTIS.domain.UserMgmt.UserProfile.UserProfileMD))]
    public partial class UserProfileInvnMgmt : UserProfile
    {

    }
}

现在 InventoryMgmt edmx 中还有 PO Header。这是 EF 生成的类(注意它引用了 UserProfileInvnMgmt UserProfile,它是 CreatedById 的外键表):

namespace OTIS.domain.InventoryMgmt
{
    using System;
    using System.Collections.Generic;

    public partial class POHeader
    {
        public POHeader()
        {
            this.PODetails = new HashSet<PODetail>();
        }

        public int Id { get; set; }
        public int FacilityId { get; set; }
        public int VendorId { get; set; }
        public int StatusId { get; set; }
        public string Notes { get; set; }
        public int CreatedById { get; set; }
        public System.DateTime CreatedOn { get; set; }
        public int ModifiedById { get; set; }
        public System.DateTime ModifiedOn { get; set; }

        public virtual ICollection<PODetail> PODetails { get; set; }
        public virtual Vendor Vendor { get; set; }
        public virtual POHeaderStatus POHeaderStatus { get; set; }
        public virtual UserProfileInvnMgmt UserProfile { get; set; }
        public virtual UserProfileInvnMgmt UserProfile1 { get; set; }
    }
}

现在我有一个将 POHeader 类实体转换为视图模型的方法。在设计期间,它允许我将 POHeader.UserProfile.FullName 分配给视图模型属性 OrderedBy。

public IEnumerable<POHeadersListViewModel> ConvertClassToViewModel(IEnumerable<POHeader> purchaseOrders)
    {
        IEnumerable<POHeadersListViewModel> poGrid =
            from l in purchaseOrders.ToList()
            select new POHeadersListViewModel()
            {
                Id = l.Id,
                VendorName = l.Vendor.VendorName,
                OrderedBy = l.UserProfile.FullName,
                OrderDate = l.CreatedOn,
                Status = l.POHeaderStatus.DisplayName
                //OwnerName = l.Customer == null ? "" : l.Customer.CustomerName
            };

        return poGrid;
    }

但是,当您运行此代码时,没有为 OrderedBy 分配任何值,并且如果在调试时展开 IEnumerable purchaseOrders 变量,您会看到 UserProfile,但如果您将其展开,则看不到 FullName 属性,但是FirstName 和 LastName 已填充。视图模型中的结果值或 OrderBy 是一个空格,这似乎返回了 FullName 属性,但 FirstName 和 LastName 为空,导致 FullName 只返回应该分隔 FirstName 和 LastName 属性的空格,即

public string FullName
    {
        get
        {
            return this.FirstName + " " + this.LastName;
        }
    }

但请注意,如果我这样做:

OrderedBy = l.UserProfile.FirstName + " " + l.UserProfile.LastName,

它有效,所以 FirstName 和 LastName 不为空。关于为什么没有正确返回 FullName 的任何想法?一般来说,处理多个版本的 UserProfile 是最好的方法吗?

【问题讨论】:

    标签: c# asp.net-mvc entity-framework


    【解决方案1】:

    不确定这是您的问题,但您的部分类扩展了 IEntity public partial class UserProfile : IEntity,而 auto-gen 类没有。我相信这些应该完全匹配,还是 C# 允许你这样做?

    更新我相信您的问题是您正在尝试在 linq 查询中使用派生/计算属性,当您考虑使用 EF 将其映射回您的数据库时不会是这样能够处理/翻译。这个讨论似乎很相关:Using a partial class property inside LINQ statement

    【讨论】:

    • 感谢您的回复。似乎 C# 允许这样做。 IEntity 接口在这样的代码的其他部分中正常工作。另外,Auto Gen 的代码不可能把它放进去。所以肯定有其他原因。
    • 您是否尝试过设置断点并单步执行以查看发生了什么?另外,感谢您对此的更新。
    • 是的,请参阅上面以“但是,当您运行此代码时...”开头的部分
    • 重新阅读并查看您使用派生属性为我提供的线索...查看修订后的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-13
    • 2017-11-28
    • 1970-01-01
    相关资源
    最近更新 更多