Serialize LINQ to SQL

I get a very long strange error when I try to serialize this.

On this line
ser.WriteObject(stream1, casenames)

Open in new window


 I assume it is because I have a select in there and thus not the full table.  

I am using LINQ to SQL and have the DataMember DataContract attributed decorating my Entity Classes.

Dim db As New DataClasses1DataContext

        Dim casenames = (From cn In db.tbl_tests Where cn.Bear = lc _
                         Select cn.Kan, cn.Sach, cn.LuT).First


        Dim stream1 As New MemoryStream()
        Dim ser As New DataContractJsonSerializer(GetType(tbl_test))
        ser.WriteObject(stream1, casenames)
        Debug.Print(Encoding.UTF8.GetString(stream1.ToArray()))

Open in new window


Could someone please help.
LVL 20
darbid73Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
See: http://stackoverflow.com/questions/2307173/passing-an-instance-of-anonymous-type-over-wcf

The short answer is: Don't, just return a real type (either the table, or a separate class you've created specifically for this scenario).

The long answer is: It is possible, but not by default.
0
darbid73Author Commented:
Ok let me understand the problem.

My object t(hat is the table) has the attributes decorated, but this will only work if I try to serialize whole table.  If i start picking pieces out then it is going to fail.

My choices are

1. Create now my own classes for each individual query that I might possibly use and then refer to them in serialization
2. Return the whole table and then just get the parts that I want. (seems like a waste but if the table is not too big then ok)

or

can I decorate these fields with something to identify that I might just want them.
0
Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
Your choices are correct. You cannot assign attributes to the anonymous type.

A third choice would be to write your own serializer that supports anonymous types. But it would be against best practices to do so. If your're serializing data or passing data through WCF, it's a best practice to fully spec the type, that allows you to do backwards compatibility and other maintainability scenario's later on. Your anonymous types will turn into a maintenance nightmare pretty quickly otherwise.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

darbid73Author Commented:
Great thanks.

So right now LINQ to SQL wrote all my Entity classes for me and I imagine updates them if the tables change.  I just had to change the Serialization to undirectional, so that the decorations were added.

So I now have to write my own decorated classes for any special queries I want to do, then I have to maintain them and change them if I update anything with respect to them.

Is this the right direction?
0
Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
You're doing great :)
0
Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
You might want to check out Entity Framework though, Linq-2-SQL isn't going to evolve any further in the near future and Microsoft has shifted all its resources to Entity Framework.

Release 4.1 is almost ready (RC stage, with GoLive license) and it supports Code first development. That way you just specify your classes and EF will do the dataaccess for them (without any ugly code inside your classes).

http://thedatafarm.com/blog/data-access/new-ef4-amp-ef4-1-content-on-msdn/
0
Bob LearnedCommented:
I don't see the error that you are getting, so you should address that, to determine the best course of action.  Entity Framework has its own set of problems, when it comes to JSON serialization, so it wouldn't be a panacea.
0
Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
Entity Framework 4.1 Code First solves a lot of the JSon issues, as it allows you to use plain object classes.
0
darbid73Author Commented:
I don't see the error that you are getting, so you should address that,
Hi T.L.O.

If I hover my mouse over "casenames" like it is now it will something with the word "anonymous" in it.  If I take off the select then it will show the table "tbl_test".

But the error message is massive and does not make any sense to me.

Actually in the link above to stackoverflow this message here is similar i think - although this is the second part there is a lot more

Type '<>f__AnonymousType0`2[System.String,System.String]' cannot be serialized.
Consider marking it with the DataContractAttribute attribute, and marking all
of its members you want serialized with the DataMemberAttribute attribute.  
See the Microsoft .NET Framework documentation for other supported types.

0
Bob LearnedCommented:
One possibility, is to select into a POCO class that you define:

Example:

Select New Person With  { .FirstName = f.FirstName, .LastName = f.LastName }

Open in new window


I am a C# developer, and the translation of LINQ to VB.NET may not always be correct, so any suggestions are just proof-of-concept.
0
Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
Yes, this is what we decided on before:

1. Create now my own classes for each individual query that I might possibly use and then refer to them in serialization

0
Bob LearnedCommented:
I was distracted by the talk of Entity Framework, and other such discussions, and missed that one line in the author's comment...
0
darbid73Author Commented:
Ok I hope I am up with you guys.  I think you are showing me what I want to do, just I might need to know the right steps.

So I have now created a new class decorated with datacontract / datamembers and the class only has 3 properties to match my select.

Now I only know how to do this the long way, eg

Dim casenames = (From cn In db.tbl_tests Where cn.Bear = lc _
                         Select cn.Kan, cn.Sach, cn.LuT).tolist

Dim res As New List(Of c_Special)

        For Each cn In casenames

            res.Add(New c_Special(cn.Kan, cn.Sach, cn.LuT))

        Next

Open in new window

Then I can serialize c_Special.

So I think TLO you are trying to get me to do this in one step?

0
Bob LearnedCommented:
You can do the select into a List(Of class) in one step, but if you feel comfortable with your results (small data sets), then I would go with your process.  If you have large datasets, then that extra For loop step is not optimized.
0
Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
Dim casenames = (From cn In db.tbl_tests Where cn.Bear = lc _
                         Select New c_Special(cnKan, cnSach, cnLuT)).tolist()

or:

Dim casenames = (From cn In db.tbl_tests Where cn.Bear = lc _
                         Select New c_Special With {.Kan = cnKan, .Sach = cnSach, .LuT = cnLuT}).tolist()



You can put the object creation in the select statement, no need to loop through the results and build another list.

Other than that, you're all set.
0
darbid73Author Commented:
is your suggestion above the C# way of doing this?

some thing like this
Dim casenames = (From cn In db.tbl_tests Where cn.Bear = lc _
                         Select New c_Special With ( .Kan = cn.Kan, .Sach = cn.Sach, .LuT = cn.LuT )).tolist

Open in new window


I am not on my PC to see this working thus the words "something like this"


0
Bob LearnedCommented:
Anytime you see Select, New, and With, that is the VB.NET way.  Also, you need the braces, and not parentheses.
0
Jesse HouwingScrum Trainer | Microsoft MVP | ALM Ranger | ConsultantCommented:
This syntax became available in .NET 3.0 (vs 2005).

It allows you to create an object and assign the property values without having to create a separate overload of your constructor for each property combination.

It is basically the same as:

dim obj = New obj()
with obj
  .PropertyA = valueA
  .PropertyB = vallueB
end with

but it steamlines the syntax a little further. This was available in C# in earlier versions, but was introduced in VB.NET recently. So you could call it the C# way of doing things, but it is actually a fully supported new feature to VB.NET. They're called object initializers.

A full description can be found here:
http://msdn.microsoft.com/en-us/library/ms364068(v=vs.80).aspx
0
darbid73Author Commented:
I got back to my working computer and could try it after all. For a single this works

Dim casenames = (From cn In db.tbl_tests Where cn.Bear = lc _
                         Select  New c_Special ( cn.Kan, cn.Sach, cn.LuT )).single

Open in new window


So I imagine it all works the same for a list.
0
Bob LearnedCommented:
I guess that it would as long as you have a constructor for the c_Special class, but I haven't done that with VB.NET syntax, so I didn't think that it was supported.  Thank you for the clarification!!
0
darbid73Author Commented:
Thanks guys.

To finish off this thread I would like to add something here about whether letting WCF do the serialization or to do it yourself.

The problem is if you return a string in your WCF and do the serialization with the datacontractjsonserializer then you will get "QUOTES" wrapped around your result.

Depending on the consumer this is not good.

Thus at the end of the day the way I have dealt with this in keeping with my above is that I am returning my class above or List(of myclass) then letting WCF do the serialization.  Also I made WCF wrap the result so that the JSON has an outer name.

My consumer is an iphone app.

Thus my end result looks like this

{"counselResult":[{"cwID":1,"cwshortname":"DON","cwlastname":"Duck","cwfirstname":"Donald"},{"cwID":2,"cwshortname":"SPA","cwlastname":"Sparrow","cwfirstname":"Jack"}]}

Open in new window


Where the name "counselresult" is just how WCF wraps it.

Thank you guys.

As I am sure I am only about a day or 2 from my next question I hope I share points here in an approving manner.
0
darbid73Author Commented:
Thank you again.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
WCF

From novice to tech pro — start learning today.