locked
Private Properties VS Dynamic Data RRS feed

  • Question

  • User-1395392389 posted

    Hi all,
    this one seems to me a bit too gross, so I'm probably missing something.
    Here's what I'm experiencing:

    • I have set up my entity model associated with my ASP.Net DynamicData Website.
    • In an Entity of mine, I've overridden the default (public) visibility of a property, I changed it to private.
      I need to do that, I want to expose that property in a more structured manner.
    • *Problem*: in any Dynamic Page where that entity is involved, I get a NullReference Exception whose stacktrace points to
      System.Web.DynamicData.MetaColumn.get_Attributes()...

    Now... I'm curious, so I tried to replicate the executed code in order to understand why that happened. My implementation sounds like...

    // table is the contextual MetaTable
    ICustomTypeDescriptor td = 
        TypeDescriptor.GetProvider(table.EntityType).
        GetTypeDescriptor(table.EntityType);
    PropertyDescriptorCollection props = td.GetProperties();
    foreach (PropertyDescriptor prop in props)
    {
        Response.Write(prop.Name + "<br />");
    }

     ...and effectively the property I'm looking for doesn't show up.
    But the DynamicData site tries to process it the following way (Reflector):

    AttributeCollection source = this.PropertyDescriptor.Attributes;
     ...where PropertyDescriptor (internal member of MetaColumn class) is built the following way...
    // this is the contextual MetaColumn
    TypeDescriptor.GetProvider(table.EntityType).
        GetTypeDescriptor(table.EntityType).Find(this.Name, true);
    // this returns null

     So, when the Attributes property gets called the NullReference Exception is thrown.[:(]

    Question: what am I missing?
    I can "easily" by-pass this by customizing the pages for this entity in order to avoid the handling of that problematic property. But is there a neat way to obtain that?

    Thanks in advance. 

    Tuesday, January 6, 2009 3:34 PM

All replies

  • User-1005219520 posted

    You want to avoid editing the wizard generated data model. To hide a property (column), use the [ScaffoldColumn(false)]
     attribute in your entity partial class. See ScaffoldColumnAttribute Class  and How to: Customize Data Field Appearance and Behavior For Non-Intrinsic Data Types in the Data Model

    Tuesday, January 6, 2009 3:45 PM
  • User-1395392389 posted

    Sure, I obviously did it. I didn't mention that in my previous post, sorry.

    // ...as part of my Metadata class
    [ScaffoldColumn(false)]
    private string XmlData { get; set; }
     Of course (or maybe not) the property has to be marked private. If public, in fact, I would get an InvalidOperationException because my Metadata tries to handle an "unknown property or field".
    I think this idiosyncratic behavior is strictly related to my problem: it's like you handle only public stuff on one side and everything (public | private ...) on the other, and expect same results (?)... just wondering...
    Tuesday, January 6, 2009 4:10 PM
  • User-499695227 posted

     I'm having the exact same problem when I mark a property as private.

    I want to make my foreign key fields private and only expose the referenced object, for example on a OrderDetail class make the OrderId property private so it exposes just the Order instance instead.

     That's reasonable right?  I get the same error.

    Also, I've found that it doesn't like it when I map a column (I'm using linq to sql btw) to a field vs a property.  I get an exception of trying to cast a FieldInfo to a PropertyInfo.  This isn't a real big deal, but annoying that I'm forced to use properties.

    The one that is really frustrating is when I try to make my primary keys readonly.  When I do that, and when I try to update the entity using dynamic data I get a "Row not found or changed.".  And it wont let me delete records when the primary key is readonly.  I'm using the 7/16 futures release, maybe that has something to do with it, I need to check if this happens on a standard dynamic data site.

     

    Can I override any of the dynamic data classes to get arround these limitations?

    Friday, May 8, 2009 9:26 AM
  • User-1005219520 posted

    >> I'm having the exact same problem when I mark a property as private

    Changing the access level in the data model is the wrong approach. In general you should not modify the generated data model. How are you mapping columns to fields? If you want to hide FKs, use ScaffoldColumn(false).

    >>on a OrderDetail class make the OrderId property private so it exposes just the Order instance instead.

    That is the wrong approach. Making it private only breaks navigation.

    >>make my primary keys readonly.

    PKs are RO. Again, don't change the data model unless you have a good reason. You should be using the entity partial class with the proper attributes.

    Friday, May 8, 2009 11:28 AM
  • User-499695227 posted

    I'm trying to design from a domain/model driven approach.

    I'm not modifying any generated code, I'm mapping the model to the database myself with [Column] attributes.  You don't have to use the O/R designer to use linq to sql you know.

     So why would wanting to make something private be the wrong approach?  It's basic OO to only expose what you really have to.  Dynamic data may not be the only client of my model.

    If DD needs public foreign key fields to navigate, I guess I can live with that, but I don't think its wrong to want your model expressed in terms of objects instead of keys.

     Still, I don't want everything that is persisted by linq to sql to have to be public.  I don't see why this wouldn't already be supported.  Why can't it just ignore anything non-public?

    Anyone know of a way arround this?

    Friday, May 8, 2009 7:12 PM
  • User-330204900 posted

    Have you tried setting those tables you want as private wil the scaffold false attribute? this may make DD not bother with them.

    Saturday, May 9, 2009 4:10 AM
  • User-499695227 posted

     Yes, I have put [ScaffoldColumn(false)] on those properties but it still gives a NullReferenceException at MetaColumn.get_Attributes()

     The only thing that seems to make dynamic data ignore them is by putting IsDbGenerated = true in the L2S column attribute, but that doesn't work because then linq will throw an exception if i try to change the value. (of course)

    Saturday, May 9, 2009 9:25 AM
  • User-330204900 posted

    That does seem to be a problem [:(] do you need to set the table protected for some other code?

    Saturday, May 9, 2009 12:34 PM
  • User-499695227 posted

     Yes, there are lots of reasons why you would want to make certain fields private.  Its basic object oriented design to try and limit the amount of information your classes provide (information hiding, encapsulation, tell don't ask principle, etc.)

     Also, dynamic data won't be the only code interacting with my object model, so I don't want to compromise the clarity of the model just to satisfy dynamic data.  Some things I can live with, like if it needs foreign keys exposed so navigation works, ok, but I don't like having to make everything that linq to sql persists to be public.

     I guess I'll look into creating a custom metadata provider, is that the right way to go?

     I would also like to submit this as a feature request to the dynamic data team, do you know how I would go about that?

     

    Sunday, May 10, 2009 7:55 PM
  • User-330204900 posted

    The team frequent this forum all the time, see the earlier post by Rick.

    Monday, May 11, 2009 3:35 AM
  • User-1005219520 posted

    This is not a Dynamic Data issue. Please create a console application that lists, naviages the entities. Change the access to private and you will get the same exception. Then Post LINQ To SQL here -- don't mention Dynamic Data.

    Monday, May 11, 2009 11:25 AM
  • User-499695227 posted

      Rick, I don't get what you are saying.  If I have a class with a private member on it, from the perspective of client code that uses that class, that member doesn't exist.

    If I make a console app and try to reference a private property, it won't even compile.

    What I'm wanting here is for dynamic data to act like any other user of a class, meaning it should treat anything non-public, like it does not exist.

    Instead, dynamic data is collecting all members of my entity class that have [Column] attributes on them regardless of their access level.  This causes the null reference exception.  This is a dynamic data issue.

     Here is an example:

    1    [Table("Orders")]
    2 class Order {
    3
    4 [Column]
    5 public string OrderNumber { get; set; } //This works fine
    6
    7 // I don't want this as part of my model but
    8 // I still need l2s to persist it for me.
    9 // I want dynamic data to ignore it but this
    10 // causes an error

    11 [Column]
    12 private string StatusCode { get; set; }
    13 }
      
    Monday, May 11, 2009 6:32 PM
  • User-1005219520 posted

    I opened a bug on this.

    Tuesday, May 12, 2009 6:35 PM
  • User-499695227 posted
    Thanks Rick.

    Is there a public website where I could check the status of bugs in dynamic data, or is it internal to Microsoft?

    Also, I have a workaround I am using in preview 4, in the GetScaffoldColumns override in the CustomMetaTable class where I filter only public properties.  But, private fields and private enum properties for some reason still cause problems.  I'm guessing I should instead be implementing an ICustomTypeDescriptor?
    Sunday, May 31, 2009 9:34 AM
  • User1309420260 posted

    Any new news about it?

    Vs 2010 sp1, in april 2011 same problem... any solution, workaround?

    Friday, April 15, 2011 6:02 PM
  • User-330204900 posted

    You could look into EF 4.1 and Code first?

    Saturday, April 16, 2011 2:39 PM
  • User1309420260 posted

    Moving to ef 4.0/4.1 => .net 4.0 in my model => .net 4.0 in my client web app, web service and so on...

    but that's my problem...

    anyway, i renounced to entities because to much problem with sql ce in 3.5 version...

    thanks! P.S. i read almost the entire your blog in 2 days:-)

    Sunday, April 17, 2011 6:22 AM
  • User-330204900 posted

    That is some feat you deserver an award if I had one to give Laughing

    Sunday, April 17, 2011 6:53 AM