Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with filling the nested DTO #13

Closed
girishmandhale opened this issue Jan 27, 2016 · 7 comments
Closed

Issue with filling the nested DTO #13

girishmandhale opened this issue Jan 27, 2016 · 7 comments

Comments

@girishmandhale
Copy link

Hi Jon,

I want to fill my DTO's with nested DTO. I tried as you explained on your wiki site but no luck. Can you please take a look and let me know what i am missing. Below are my classs

[Table("template_mgt.BuildTemplate")]
public partial class BuildTemplate
{

    public BuildTemplate()
    {
        BuildTemplateFields = new HashSet<BuildTemplateField>();
    }
    [Key]
    public int BuildTemplateID { get; set; }



    [Required]
    [StringLength(150)]
    public string BuildTemplateName { get; set; }

    [Required]
    [StringLength(150)]
    public string BuildTemplateFriendlyName { get; set; }


    public  ICollection<BuildTemplateField> BuildTemplateFields { get; set; }
}

[Table("template_mgt.BuildTemplateField")]
public partial class BuildTemplateField
{
[Key]
public int BuildTemplateFieldID { get; set; }

    public int? BuildTemplateID { get; set; }


    public   BuildTemplate BuildTemplate { get; set; }
}

Below are my corresponding DTO classes

--- BuildTemplateDTO class has a ienumarable that i need to fill.
public class BuildTemplateDTO : EfGenericDto<BuildTemplate, BuildTemplateDTO >
{
public int BuildTemplateID { get; set; }

    public string BuildTemplateName { get; set; }

    public string BuildTemplateFriendlyName { get; set; }


    public string BuildTemplatePurpose { get; set; }



    public  IEnumerable<BuildTemplateFieldDTO> BuildTemplateField { get; set; }

    public BuildTemplateDTO()
    {

        BuildTemplateField = new List<BuildTemplateFieldDomain>();
    }


    protected override CrudFunctions SupportedFunctions
    {
          get { return   CrudFunctions.Update |CrudFunctions.Detail ; } 
    }

    protected override Type AssociatedDtoMapping
    {
        get { return typeof(BuildTemplateFieldDomain); }
    }



}

public class BuildTemplateFieldDto: EfGenericDto<BuildTemplateField, BuildTemplateFieldDto>
{

    public int BuildTemplateFieldID { get; set; }

    public int? BuildTemplateID { get; set; }

    public  BuildTemplateDomain BuildTemplate { get; set; }

    protected override CrudFunctions SupportedFunctions
    {
        get { return CrudFunctions.AllCrud | CrudFunctions.DoesNotNeedSetup; }
    }


}

Thanks in advance.

Thank You
Girish

@girishmandhale
Copy link
Author

Typo mistake please consider any Domain object as Dto above.

@JonPSmith
Copy link
Owner

HI @girishmandhale,

I'm not sure what you mean by 'no luck' - does it not work at all? If the Detail service doesn't return anything, or is missing the nested DTO that is one thing. If the Detail service works but your Update service call does not update the BuildTemplateFields list then that is another. I ask this as update of a nested set of dtos is difficult.

If the detail service works but the update service doesn't then have a look at the CrudCustomerAddressDto class, especially lines 65 to 70. This is an example of a Nested DTO with updates. You will see for an update to work then you need to load both the parent and the child relationships for an update to work.

One other point in your example is that I don't see the correct EfGenericDto<,> definition. If this is really the case then nothing would work. I would have expected to see each DTO start with:

For BuildTemplateDTO it should have : EfGenericDto<BuildTemplate,BuildTemplateDTO>
For BuildTemplateFieldDto it should have : EfGenericDto<BuildTemplateField,BuildTemplateFieldDto>

I hope that helps.

@JonPSmith JonPSmith reopened this Jan 27, 2016
@girishmandhale
Copy link
Author

Hi John,

Thanks for your quick reply. Yes it was not working. But i did a few changes and it is working now. Please have a look into my below classes. I have not done any additional mapping . I am using the

[Table("template_mgt.BuildTemplate")]
public partial class BuildTemplate
{

    public BuildTemplate()
    {
        BuildTemplateFields = new HashSet<BuildTemplateField>();
    }
    [Key]
    [Column(Order = 0)]
    public int BuildTemplateID { get; set; }

    [Required]
    [StringLength(150)]
    public string BuildTemplateName { get; set; }


    public  ICollection<BuildTemplateField> BuildTemplateFields { get; set; }
}

[Table("template_mgt.BuildTemplateField")]
public partial class BuildTemplateField
{

    [Key]
    [Column(Order = 1)]
    public int BuildTemplateFieldID { get; set; }

    [Key]
    [Column(Order = 0)]
    public int? BuildTemplateID { get; set; }

    public   BuildTemplate BuildTemplate { get; set; }
}

public class BuildTemplateFieldDto : EfGenericDto<BuildTemplateField, BuildTemplateFieldDto>
{

    public int BuildTemplateFieldID { get; set; }

    public int? BuildTemplateID { get; set; }

    public  BuildTemplateDto BuildTemplate { get; set; }

    protected override CrudFunctions SupportedFunctions
    {
        get { return CrudFunctions.AllCrud | CrudFunctions.DoesNotNeedSetup; }
    }


}

public class BuildTemplateDto : EfGenericDto<BuildTemplate, BuildTemplateDto>
{

    public int BuildTemplateID { get; set; }



    [Required]
    [StringLength(150)]
    public string BuildTemplateName { get; set; }

    [Required]
    [StringLength(150)]
    public string BuildTemplateFriendlyName { get; set; }

    public ICollection<BuildTemplateField> BuildTemplateFields { get; set; }


    protected override CrudFunctions SupportedFunctions
    {
        get { return CrudFunctions.Update | CrudFunctions.Detail; } 
    }


}

I am calling update service

        IUpdateSetupService service = DependencyResolver.Current.GetService(typeof(IUpdateSetupService)) as IUpdateSetupService;

        int id = 15;
        var dto = service .GetOriginal<BuildTemplateDto>(id).Result;
        return dto;

As i am very new to EF i am having couple of queries.

  1. Now we don't have AssociatedDtoMapping in BuildTemplateDto then sill i am getting the data in the nested DTO can you please explain on this.

  2. Can we call stored procs using the generic services which service you prefer for gettng the data (select)

Thank You
Girish Mandhale

@JonPSmith
Copy link
Owner

OK, I will answer your questions in sequence:

  1. No AssociatedDtoMapping but still works. My question is - do you use BuildTemplateFieldDto anywhere else in your code? The mapping just has to be set up once for a build (AutoMapper holds the mapping in a static). If you want to see if this is happening then a) rebuild your solution b) then immediately try your IUpdateSetupService (no other GenericServices calls ahead of that). I think it should fail because the mapping isn't set up for BuildTemplateFieldDto.
  2. Can you use Stored Procs. No you can't as Stored Procs have a specific call method. AutoMapper forms a LINQ command that defines all the tables/columns that need to be accessed, so this cannot be mapped to a Stored Proc. You might like to read my article on EF, which talks about Stored Procs near the end.

Finally I would say that even if you have the IUpdateSetupService service working without the points I raised in the last answer you won't find that the IUpdateService will work, i.e. it won't properly update the Fields (I can't remember what goes wrong - I think you get both the old and the new Fields instead of replacing the existing Fields with the new/updated Fields).

@girishmandhale
Copy link
Author

Thanks Jon. Thanks for resolving above queries. I am using these generic services in my application. We are having some specific scenarios where we need to GET(Read) the data through SQL stored proc as well as Oracle Db. I want to just get the data for the READ operation. Is it possible through GenericServices?

@JonPSmith
Copy link
Owner

I think you are best to use EF directly for your SQL Stored Proc. There are ways you can map SQL Stored Procs to a class in such as way that GenericServices can use it, but there isn't really any gain to using GenericServices in this case because it cannot do any mapping, as I explained in my last answer.

There is not problem using GenericServices on some calls and calling EF directly for other accesses. I do it myself. Therefore you can use GenericServices on 'normal' accesses and then EF for an access that needs specific EF features, in this case accessing Stored Procs.

@girishmandhale
Copy link
Author

Thanks Jon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants