Вставьте / Обновление с сервисами RIA Композиционный Атрибут

Я создаю приложение Silverlight 4 с Платформой Объекта, RIA Services и MVVM-легким инструментарием. Приложение имеет дело с диаграммой составного объекта, которая содержит следующую структуру:

  • Задание 1->* ресурсов
  • Задание 1->* планов работ
  • План работ 1->* WorkplanItems
  • Ресурс 1->* присвоений
  • Присвоение WorkplanItems 1->*

Я хотел бы смочь загрузить задание (использование Включают атрибуты/директиву), и это хорошо работает. загрузить полный график из корня определенного задания. Однако то, когда я отправляю, возвращается, я получаю ошибку

Entity for operation '0' has multiple parents

Это было мое понимание из этого сообщения, что атрибут Состава на моих метаданных - то, что должно позволить мне отправлять это как полный график и затем обрабатывать обновление всех объектов на сервере правильно с единственным распространением в прямом и обратном направлениях из моего приложения 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 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 WorkplanItems { get; set; }

        [Display(AutoGenerateField = false)]
        [Include]
        [Composition]
        public EntityCollection Workplans { get; set; }


        [Display(AutoGenerateField = false)]
        [Include]
        [Composition]
        public EntityCollection 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="",ApplyFormatInEditMode=true)]
        public Nullable 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 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 Assignments { get; set; }

        public string Description { get; set; }

        [Include]
        public Job Job { get; set; }

        public int JobID { get; set; }

        public EntityCollection PendingTimesheets { get; set; }

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

1
задан Ryan from Denver 29 July 2010 в 17:50
поделиться

1 ответ

Я нашел решение моей проблемы. Это действительно очень эффективно, если вы поймете некоторые из этих внутренних механизмов и предостережений:

  1. Применяйте атрибуты [Composition] и [Include] только к корню вашего графа объектов.
  2. Ваш корневой объект Composition - это то, что отправляется, и именно здесь начинается ваш процесс обновления.
  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; }
    }
}

Если у кого-то есть другие советы / идеи, пожалуйста, добавьте их. Я продолжу публиковать больше, когда узнаю больше.

2
ответ дан 2 September 2019 в 22:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: