1

我正在使用Entity Framework,RIA Services和MVVM-Light工具包創建Silverlight 4應用程序。 > *資源 使用RIA服務插入/更新組合屬性

  • 作業1 - - > *工作計劃
  • 工作計劃1 - > * WorkplanItems
  • 資源1​​

    • 伯1:用一個複雜的對象圖,包含下面的結構的應用程序處理 - > *分配
    • WorkplanItems 1 - > *分配

    我希望能夠(使用包含屬性/指令)來加載工作,這個工作精細。從特定作業的根加載完整圖形。然而,當我更改提交回,我得到一個錯誤

    Entity for operation '0' has multiple parents 
    

    它已經從this post我的理解是,在我的元數據組成的屬性是什麼應該允許我提出這是一個完整的圖形,然後處理更新的服務器上的所有對象正確地從我的Silverlight應用程序進行一次往返。我的目標是不要在每次更改時提交更改,但要允許用戶對作業進行一系列更改,並將其與相關部分進行更改,然後提交或取消更改。

    請讓我知道,如果你知道我忽略了這個問題嗎?這裏是我設置的元數據:

    // The MetadataTypeAttribute identifies AssignmentMetadata as the class 
    // that carries additional metadata for the Assignment class. 
    [MetadataTypeAttribute(typeof(Assignment.AssignmentMetadata))] 
    public partial class Assignment 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Assignment class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class AssignmentMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private AssignmentMetadata() 
         { 
         } 
    
         public decimal CostBudgeted { get; set; } 
    
         public decimal CostRemaining { get; set; } 
    
         public decimal HoursBudgeted { get; set; } 
    
         public decimal HoursRemaining { get; set; } 
    
         public bool IsComplete { get; set; } 
    
         public int ItemID { get; set; } 
    
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public Resource Resource { get; set; } 
    
         public int ResourceID { get; set; } 
    
         public Workplan Workplan { get; set; } 
    
         public int WorkplanID { get; set; } 
    
         public WorkplanItem WorkplanItem { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies JobMetadata as the class 
    // that carries additional metadata for the Job class. 
    [MetadataTypeAttribute(typeof(Job.JobMetadata))] 
    public partial class Job 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Job class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class JobMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private JobMetadata() 
         { 
         } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         [Display(Name="Client Job", Order=2, Description="Is this a client job?")] 
         [DefaultValue(true)] 
         public bool IsRealJob { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         public JobDetail JobDetail { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public int JoblID { get; set; } 
    
         [Display(Name="Job Title", Order=1, Description="What should this job be called?")] 
         public string Title { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<WorkplanItem> WorkplanItems { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<Workplan> Workplans { get; set; } 
    
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<Resource> Resources { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies JobDetailMetadata as the class 
    // that carries additional metadata for the JobDetail class. 
    [MetadataTypeAttribute(typeof(JobDetail.JobDetailMetadata))] 
    public partial class JobDetail 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the JobDetail class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class JobDetailMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private JobDetailMetadata() 
         { 
         } 
    
         [Display(Name="Client", Order=1,Description="Name of the Client")] 
         public string Client { get; set; } 
    
         [Display(Name = "Client Fee", Order = 5, Description = "Client Fee from Engagement Letter")] 
         [DisplayFormat(DataFormatString="C",NullDisplayText="<Not Set>",ApplyFormatInEditMode=true)] 
         public Nullable<decimal> ClientFee { get; set; } 
    
         [Display(AutoGenerateField=false)] 
         public int ClientIndex { get; set; } 
    
         [Display(AutoGenerateField = true)] 
         public string EFOLDERID { get; set; } 
    
         [Display(Name = "Engagement Name", Order = 4, Description = "Friendly name of the Engagement")] 
         public string Engagement { get; set; } 
    
         [Display(Name = "Eng Type", Order = 3, Description = "Type of Work being done")] 
         public string EngagementType { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public Job Job { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public int JobID { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public int PEJobID { get; set; } 
    
         [Display(Name = "Service", Order = 2, Description = "Service Type")] 
         public string Service { get; set; } 
    
         [Display(Name = "Timing of the Work", Order = 6, Description = "When will this work occur?")] 
         public string Timing { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies PendingTimesheetMetadata as the class 
    // that carries additional metadata for the PendingTimesheet class. 
    [MetadataTypeAttribute(typeof(PendingTimesheet.PendingTimesheetMetadata))] 
    public partial class PendingTimesheet 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the PendingTimesheet class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class PendingTimesheetMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private PendingTimesheetMetadata() 
         { 
         } 
    
         public decimal PendingHours { get; set; } 
    
         public string UserName { get; set; } 
    
         public DateTime WorkDate { get; set; } 
    
         [Include] 
         public Workplan Workplan { get; set; } 
    
         public int WorkplanID { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies ResourceMetadata as the class 
    // that carries additional metadata for the Resource class. 
    [MetadataTypeAttribute(typeof(Resource.ResourceMetadata))] 
    public partial class Resource 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Resource class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class ResourceMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private ResourceMetadata() 
         { 
         } 
    
         [Include] 
         [Composition] 
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         [Include] 
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public decimal Rate { get; set; } 
    
         public int ResourceID { get; set; } 
    
         public string Title { get; set; } 
    
         public string UserName { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies WorkplanMetadata as the class 
    // that carries additional metadata for the Workplan class. 
    [MetadataTypeAttribute(typeof(Workplan.WorkplanMetadata))] 
    public partial class Workplan 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Workplan class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class WorkplanMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private WorkplanMetadata() 
         { 
         } 
    
         [Include] 
         [Composition] 
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         public string Description { get; set; } 
    
         [Include] 
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public EntityCollection<PendingTimesheet> PendingTimesheets { get; set; } 
    
         public Nullable<int> PETaskID { get; set; } 
    
         public decimal TtlCost { get; set; } 
    
         public decimal TtlHours { get; set; } 
    
         public DateTime WorkEnd { get; set; } 
    
         public int WorkplanID { get; set; } 
    
         [Include] 
         [Composition] 
         public EntityCollection<WorkplanItem> WorkplanItems { get; set; } 
    
         public DateTime WorkStart { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies WorkplanItemMetadata as the class 
    // that carries additional metadata for the WorkplanItem class. 
    [MetadataTypeAttribute(typeof(WorkplanItem.WorkplanItemMetadata))] 
    public partial class WorkplanItem 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the WorkplanItem class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class WorkplanItemMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private WorkplanItemMetadata() 
         { 
         } 
    
         [Include] 
         [Composition] 
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         public string Description { get; set; } 
    
         public int ItemID { get; set; } 
    
         [Include] 
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public string Notes { get; set; } 
    
         public short Ordinal { get; set; } 
    
         [Include] 
         public Workplan Workplan { get; set; } 
    
         public int WorkplanID { get; set; } 
        } 
    } 
    
  • 回答

    2

    我已經想出瞭解決我的問題。這實際上是真正強大的,一旦你瞭解一些內部的工作和需要注意的地方:

    1. 只有[組成]和[包含]屬性應用到你的對象圖的根。
    2. 組合的根對象是提交的內容,並且是更新過程開始的位置。
    3. 您的根對象的EntityState實際上可能不代表更新(就像我的情況)。
    4. 什麼都先重新重視你的圖形,所有對象得到重視和他們的狀態被設定爲相同的值(插入,更新,刪除等)
    5. 您的圖表後重新連接你需要更新每個實體根據提交的ChangeSet。

    可能還有更多的我還沒有完全理解;但是,這在我的環境中起作用。我想找出一個更好的方法來做到這一點,但當我嘗試應用通用附加方法時,我似乎遇到了不同的問題。

    以下是我想出了我的更新方法:

    public void UpdateJob(Job currentJob) 
        { 
         //this.ObjectContext.Jobs.AttachAsModified(currentJob, this.ChangeSet.GetOriginal(currentJob)); 
    
         // compositional update process 
         foreach (Assignment a in this.ChangeSet.GetAssociatedChanges(currentJob, j => j.Assignments)) 
         { 
          ChangeOperation op = this.ChangeSet.GetChangeOperation(a); 
          switch (op) 
          { 
           case ChangeOperation.Insert: 
            InsertAssignment(a); 
            break; 
           case ChangeOperation.Update: 
            UpdateAssignment(a); 
            break; 
           case ChangeOperation.Delete: 
            DeleteAssignment(a); 
            break; 
           case ChangeOperation.None: 
            if (a.EntityState == EntityState.Detached) 
             this.ObjectContext.Assignments.Attach(a); 
            System.Data.Objects.ObjectStateEntry ose; 
            if (this.ObjectContext.ObjectStateManager.TryGetObjectStateEntry(a.EntityKey, out ose)) 
             this.ObjectContext.ObjectStateManager.ChangeObjectState(a, EntityState.Unchanged); 
            break; 
          } 
         } 
    
         foreach (WorkplanItem wpi in this.ChangeSet.GetAssociatedChanges(currentJob, j => j.WorkplanItems)) 
         { 
          ChangeOperation op = this.ChangeSet.GetChangeOperation(wpi); 
          switch (op) 
          { 
           case ChangeOperation.Insert: 
            InsertWorkplanItem(wpi); 
            break; 
           case ChangeOperation.Update: 
            UpdateWorkplanItem(wpi); 
            break; 
           case ChangeOperation.Delete: 
            DeleteWorkplanItem(wpi); 
            break; 
           case ChangeOperation.None: 
            if (wpi.EntityState == EntityState.Detached) 
             this.ObjectContext.WorkplanItems.Attach(wpi); 
            System.Data.Objects.ObjectStateEntry ose; 
            if (this.ObjectContext.ObjectStateManager.TryGetObjectStateEntry(wpi.EntityKey, out ose)) 
             this.ObjectContext.ObjectStateManager.ChangeObjectState(wpi, EntityState.Unchanged); 
            break; 
          } 
         } 
    
         foreach (Workplan wp in this.ChangeSet.GetAssociatedChanges(currentJob, j => j.Workplans)) 
         { 
          ChangeOperation op = this.ChangeSet.GetChangeOperation(wp); 
          switch (op) 
          { 
           case ChangeOperation.Insert: 
            InsertWorkplan(wp); 
            break; 
           case ChangeOperation.Update: 
            UpdateWorkplan(wp); 
            break; 
           case ChangeOperation.Delete: 
            DeleteWorkplan(wp); 
            break; 
           case ChangeOperation.None: 
            if (wp.EntityState == EntityState.Detached) 
             this.ObjectContext.Workplans.Attach(wp); 
            System.Data.Objects.ObjectStateEntry ose; 
            if (this.ObjectContext.ObjectStateManager.TryGetObjectStateEntry(wp.EntityKey, out ose)) 
             this.ObjectContext.ObjectStateManager.ChangeObjectState(wp, EntityState.Unchanged); 
            break; 
          } 
         } 
    
         foreach (Resource res in this.ChangeSet.GetAssociatedChanges(currentJob, j => j.Resources)) 
         { 
          ChangeOperation op = this.ChangeSet.GetChangeOperation(res); 
          switch (op) 
          { 
           case ChangeOperation.Insert: 
            InsertResource(res); 
            break; 
           case ChangeOperation.Update: 
            UpdateResource(res); 
            break; 
           case ChangeOperation.Delete: 
            DeleteResource(res); 
            break; 
           case ChangeOperation.None: 
            if (res.EntityState == EntityState.Detached) 
             this.ObjectContext.Resources.Attach(res); 
            System.Data.Objects.ObjectStateEntry ose; 
            if (this.ObjectContext.ObjectStateManager.TryGetObjectStateEntry(res.EntityKey, out ose)) 
             this.ObjectContext.ObjectStateManager.ChangeObjectState(res, EntityState.Unchanged); 
            break; 
          } 
         } 
    
         ChangeOperation detailop = this.ChangeSet.GetChangeOperation(currentJob.JobDetail); 
         switch (detailop) 
         { 
          case ChangeOperation.Insert: 
           InsertJobDetail(currentJob.JobDetail); 
           break; 
          case ChangeOperation.Update: 
           UpdateJobDetail(currentJob.JobDetail); 
           break; 
          case ChangeOperation.Delete: 
           DeleteJobDetail(currentJob.JobDetail); 
           break; 
          case ChangeOperation.None: 
           System.Data.Objects.ObjectStateEntry ose; 
           if (this.ObjectContext.ObjectStateManager.TryGetObjectStateEntry(currentJob.JobDetail.EntityKey, out ose)) 
             this.ObjectContext.ObjectStateManager.ChangeObjectState(currentJob.JobDetail, EntityState.Unchanged); 
           break; 
         } 
    
         if (currentJob.EntityState == EntityState.Detached) 
          this.ObjectContext.Jobs.Attach(currentJob); 
    
         ChangeOperation jobop = this.ChangeSet.GetChangeOperation(currentJob); 
         switch (jobop) 
         { 
          case ChangeOperation.Insert: 
           InsertJob(currentJob); 
           break; 
          case ChangeOperation.Update: 
           // Since this is the compositional root, we need to make sure there really is a change 
           var origJob = this.ChangeSet.GetOriginal(currentJob); 
           if (origJob != null) 
           { 
            this.ObjectContext.Jobs.AttachAsModified(currentJob, 
             origJob); 
           } 
           else 
           { 
            this.ObjectContext.ObjectStateManager.ChangeObjectState(
             currentJob, EntityState.Unchanged); 
           } 
           break; 
          case ChangeOperation.Delete: 
           DeleteJob(currentJob); 
           break; 
          case ChangeOperation.None: 
           this.ObjectContext.ObjectStateManager.ChangeObjectState(currentJob, EntityState.Unchanged); 
           break; 
         } 
    
        } 
    

    此外,這裏的變化,我不得不做出的元數據類爲我的實體。

    // The MetadataTypeAttribute identifies AssignmentMetadata as the class 
    // that carries additional metadata for the Assignment class. 
    [MetadataTypeAttribute(typeof(Assignment.AssignmentMetadata))] 
    public partial class Assignment 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Assignment class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class AssignmentMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private AssignmentMetadata() 
         { 
         } 
    
         public decimal CostBudgeted { get; set; } 
    
         public decimal CostRemaining { get; set; } 
    
         public decimal HoursBudgeted { get; set; } 
    
         public decimal HoursRemaining { get; set; } 
    
         public bool IsComplete { get; set; } 
    
         public int ItemID { get; set; } 
    
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public Resource Resource { get; set; } 
    
         public int ResourceID { get; set; } 
    
         public Workplan Workplan { get; set; } 
    
         public int WorkplanID { get; set; } 
    
         public WorkplanItem WorkplanItem { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies JobMetadata as the class 
    // that carries additional metadata for the Job class. 
    [MetadataTypeAttribute(typeof(Job.JobMetadata))] 
    public partial class Job 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Job class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class JobMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private JobMetadata() 
         { 
         } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         [Display(Name="Client Job", Order=2, Description="Is this a client job?")] 
         [DefaultValue(true)] 
         public bool IsRealJob { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public JobDetail JobDetail { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public int JoblID { get; set; } 
    
         [Display(Name="Job Title", Order=1, Description="What should this job be called?")] 
         public string Title { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<WorkplanItem> WorkplanItems { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<Workplan> Workplans { get; set; } 
    
    
         [Display(AutoGenerateField = false)] 
         [Include] 
         [Composition] 
         public EntityCollection<Resource> Resources { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies JobDetailMetadata as the class 
    // that carries additional metadata for the JobDetail class. 
    [MetadataTypeAttribute(typeof(JobDetail.JobDetailMetadata))] 
    public partial class JobDetail 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the JobDetail class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class JobDetailMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private JobDetailMetadata() 
         { 
         } 
    
         [Display(Name="Client", Order=1,Description="Name of the Client")] 
         public string Client { get; set; } 
    
         [Display(Name = "Client Fee", Order = 5, Description = "Client Fee from Engagement Letter")] 
         [DisplayFormat(DataFormatString="C",NullDisplayText="<Not Set>",ApplyFormatInEditMode=true)] 
         public Nullable<decimal> ClientFee { get; set; } 
    
         [Display(AutoGenerateField=false)] 
         public int ClientIndex { get; set; } 
    
         [Display(AutoGenerateField = true)] 
         public string EFOLDERID { get; set; } 
    
         [Display(Name = "Engagement Name", Order = 4, Description = "Friendly name of the Engagement")] 
         public string Engagement { get; set; } 
    
         [Display(Name = "Eng Type", Order = 3, Description = "Type of Work being done")] 
         public string EngagementType { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public Job Job { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public int JobID { get; set; } 
    
         [Display(AutoGenerateField = false)] 
         public int PEJobID { get; set; } 
    
         [Display(Name = "Service", Order = 2, Description = "Service Type")] 
         public string Service { get; set; } 
    
         [Display(Name = "Timing of the Work", Order = 6, Description = "When will this work occur?")] 
         public string Timing { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies PendingTimesheetMetadata as the class 
    // that carries additional metadata for the PendingTimesheet class. 
    [MetadataTypeAttribute(typeof(PendingTimesheet.PendingTimesheetMetadata))] 
    public partial class PendingTimesheet 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the PendingTimesheet class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class PendingTimesheetMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private PendingTimesheetMetadata() 
         { 
         } 
    
         public decimal PendingHours { get; set; } 
    
         public string UserName { get; set; } 
    
         public DateTime WorkDate { get; set; } 
    
         [Include] 
         public Workplan Workplan { get; set; } 
    
         public int WorkplanID { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies ResourceMetadata as the class 
    // that carries additional metadata for the Resource class. 
    [MetadataTypeAttribute(typeof(Resource.ResourceMetadata))] 
    public partial class Resource 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Resource class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class ResourceMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private ResourceMetadata() 
         { 
         } 
    
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public decimal Rate { get; set; } 
    
         public int ResourceID { get; set; } 
    
         public string Title { get; set; } 
    
         public string UserName { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies WorkplanMetadata as the class 
    // that carries additional metadata for the Workplan class. 
    [MetadataTypeAttribute(typeof(Workplan.WorkplanMetadata))] 
    public partial class Workplan 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the Workplan class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class WorkplanMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private WorkplanMetadata() 
         { 
         } 
    
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         public string Description { get; set; } 
    
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public EntityCollection<PendingTimesheet> PendingTimesheets { get; set; } 
    
         public Nullable<int> PETaskID { get; set; } 
    
         public decimal TtlCost { get; set; } 
    
         public decimal TtlHours { get; set; } 
    
         public DateTime WorkEnd { get; set; } 
    
         public int WorkplanID { get; set; } 
    
         public EntityCollection<WorkplanItem> WorkplanItems { get; set; } 
    
         public DateTime WorkStart { get; set; } 
        } 
    } 
    
    // The MetadataTypeAttribute identifies WorkplanItemMetadata as the class 
    // that carries additional metadata for the WorkplanItem class. 
    [MetadataTypeAttribute(typeof(WorkplanItem.WorkplanItemMetadata))] 
    public partial class WorkplanItem 
    { 
    
        // This class allows you to attach custom attributes to properties 
        // of the WorkplanItem class. 
        // 
        // For example, the following marks the Xyz property as a 
        // required property and specifies the format for valid values: 
        // [Required] 
        // [RegularExpression("[A-Z][A-Za-z0-9]*")] 
        // [StringLength(32)] 
        // public string Xyz { get; set; } 
        internal sealed class WorkplanItemMetadata 
        { 
    
         // Metadata classes are not meant to be instantiated. 
         private WorkplanItemMetadata() 
         { 
         } 
    
         public EntityCollection<Assignment> Assignments { get; set; } 
    
         public string Description { get; set; } 
    
         public int ItemID { get; set; } 
    
         public Job Job { get; set; } 
    
         public int JobID { get; set; } 
    
         public string Notes { get; set; } 
    
         public short Ordinal { get; set; } 
    
         public Workplan Workplan { get; set; } 
    
         public int WorkplanID { get; set; } 
        } 
    } 
    

    如果有人有其他提示/想法,請添加它們。我會繼續發佈更多,因爲我瞭解更多。