2
votes

I'm encountering an issue using Silverlight4, Ria Services and Entity Framework.

From my sl client I try to get some data through ria services, in my domainService class this method gets called:

public IQueryable<LastMinuteWachtLijstPromotie> GetLastMinuteWachtLijstPromoties(){
  IQueryable<LastMinuteWachtLijstPromotie> list = (IQueryable<LastMinuteWachtLijstPromotie>)this.ObjectContext.LastMinuteWachtLijstPromoties.Include("Promotie");

  return (from LastMinuteWachtLijstPromotie lwmp in list where lwmp.Actief select lwmp);
}

when I check the contents of the list, in debug mode, it's filled with objects of type LastMinuteWachtLijstPromotie. these objects have a navigation property to an Object named Promotie. And i can access the properties of these Promotie objects.

On the silveright client however a method gets invoked when loading is complete:

public void OnLoadEntitiesCompleted(ServiceLoadResult<T> result) {

}

In this method I get all the requested LastMinuteWachtLijstPromotie objects as expected, the property Promotie however is null.

I have set the [Include] tag on the property Promotie in the auto generated metadata class and I use the .Include("Promotie")

These same methods are used for different objects from my Domain Model, this works perfectly. Also, I cannot seem to find differences in the .edmx file with the database mappings and navigation properties.

Has anyone encountered the same issue or know a solution for it?

the metadata classes:

[MetadataTypeAttribute(typeof(LastMinuteWachtLijstPromotie.LastMinuteWachtLijstPromotieMetadata))]
        public partial class LastMinuteWachtLijstPromotie
        {

            // This class allows you to attach custom attributes to properties
            // of the LastMinuteWachtLijstPromotie 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 LastMinuteWachtLijstPromotieMetadata
            {

                // Metadata classes are not meant to be instantiated.
                private LastMinuteWachtLijstPromotieMetadata()
                {
                }

                public int AlertId { get; set; }

                public string ArtikelNummer { get; set; }

                public Nullable<int> ArtikelVariant { get; set; }

                public int LastMinuteWachtLijstPromotieId { get; set; }

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

                public int PromotieArtikelId { get; set; }

                public int PromotieId { get; set; }

                public bool Actief { get; set; }

                public DateTime Aanmaakdatum { get; set; }
            }
        }


        [MetadataTypeAttribute(typeof(Promotie.PromotieMetadata))]
    public partial class Promotie
    {

        // This class allows you to attach custom attributes to properties
        // of the Promotie 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 PromotieMetadata
        {

            // Metadata classes are not meant to be instantiated.
            private PromotieMetadata()
            {
            }

            public string ActieType { get; set; }

            public string AssortimentsManagerNaam { get; set; }

            public string AssortimentsManagerTeamIds { get; set; }

            [Display(Name = "Commerciele tekst")]
            [Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(Nokavision.ReclameFolder.UI.Web.Resources.ValidationResources))]            
            public string CommercieleTekst { get; set; }

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

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

            public Nullable<int> FrameId { get; set; }

            public Nullable<DateTime> LastMinuteWijzigingsDatum { get; set; }

            public string Opmerkingen { get; set; }

            [Display(Name = "Op wachtlijst")]
            public Nullable<bool> OpWachtLijst { get; set; }

            //public Nullable<int> PromotieCopyId { get; set; }

            public int PromotieId { get; set; }

            [Include]
            public EntityCollection<PromotieLeverancier> PromotieLeveranciers { get; set; }

            [Include]
            public EntityCollection<PromotieMutatie> PromotieMutaties{ get; set; }

            //public Nullable<int> PromotieOrigineleId { get; set; }

            [Include]
            public EntityCollection<PromotieSymbool> PromotieSymbolen { get; set; }

            public string Status { get; set; }

            [Display(Name = "Promotie inhoud")]
            public string PromotieInhoud { get; set; }

            [Display(Name = "Promotie eenheid")]
            public string PromotieEenheid { get; set; }

            [Display(Name = "Promotie prijs")]
            public decimal PromotiePrijs { get; set; }
        }
    }
3
can you add the metadata classes, especially for LastMinuteWachtLijstPromotie and Promotie?Jehof
Added them in the original post, tnxThomas
Do you defined the NavigationProperty without adding the foreign key?Jehof

3 Answers

1
votes

Add the Composition attribute to the property Promotie property of the LastMinuteWachtLijstPromotieMetadata class. Then it should work.

public partial class LastMinuteWachtLijstPromotie {
  internal sealed class LastMinuteWachtLijstPromotieMetadata{
    [Include]
    [Composition]
    public Promotie Promotie { get; set; }
  }
}
1
votes

I know this is an older thread and it may well have been answered elsewhere but I just stumbled upon it and since nobody has provided a link or a better answer.

I'm currently using Silverlight 5 and this is what worked for me (I think the process is the same in SL4 IIRC).

When propegating navigation properties to the client you need to tell RIA services that there is a relationship somewhere using the [Key] and [Association] attributes, this, not unlike the entity framework just describes how to map the relationship to the proper object.

First the metadata classes:

[MetadataTypeAttribute(typeof(Category.CategoryMetadata))]
public partial class Category
{
    internal sealed class CategoryMetadata
    {
        private CategoryMetadata() {
        }

        [Key]
        public int Id { get; set; }

        public string NAME { get; set; }

        [Association("CategoryToProducts", "Id", "CAT")]
        [Include]
        public EntityCollection<Product> Products { get; set; }
    }
}

[MetadataTypeAttribute(typeof(Order.OrderMetadata))]
public partial class Order
{

    internal sealed class OrderMetadata
    {

        // Metadata classes are not meant to be instantiated.
        private OrderMetadata() {
        }

        [Key]
        public int Id { get; set; }

        public int PRODID { get; set; }

        public DateTime DATE { get; set; }

        public bool DONE { get; set; }

        public int QTY { get; set; }

        [Association("OrderToProduct", "PRODID", "Id", IsForeignKey = true)]
        [Include]
        public Product Product { get; set; }
    }
}

[MetadataTypeAttribute(typeof(Product.ProductMetadata))]
public partial class Product
{
    internal sealed class ProductMetadata
    {
        private ProductMetadata() {
        }

        [Key]
        public int Id { get; set; }

        public int CAT { get; set; }

        public string NAME { get; set; }

        public string DESC { get; set; }

        public decimal PRICE { get; set; }

        public int QTY { get; set; }

        public long UPC { get; set; }

        [Association("ProdToCat", "CAT", "Id", IsForeignKey = true)]
        [Include]
        public Category Category { get; set; }

        [Association("ProductToOrders", "Id", "PRODID")]
        [Include]
        public EntityCollection<Order> Orders { get; set; }
    }
}

Now we need to tell RIA services we want it to load the association: (Note: Intellisense says it's a dot separated list of property names to include, however I tried something like .Include("Category.SubCategory") and this failed with an exception... though .Include("Category").Include("SubCategory") worked like a charm!)

public IQueryable<Product> GetProducts() {
    return this.ObjectContext.Products.Include("Category");
}

I can now access my "Category" property from the Silverlight client and it is not NULL :)

1
votes

Same as SilverX: just had the issue, solved it and thought it could be useful to someone.

I too had all the configuration stuff correct ([Include] for RIA S, Include() for EF) but a navigation property was still null on the Silverlight side.

Turns out the domain service method was using the [Invoke] attribute (and returning a IEnumerable<T>). Removing this attribute solved the issue.

(just for the record, [Invoke] was being used because the method had a List<Entity> parameter)