Linq and SubSonic - returning nested complex types

2019-04-13 05:25发布

问题:

I'm new to SubSonic and reasonably new to LINQ as well, so I'm just trying to put a little app together.

I've got the templates all sorted and running okay, but I've run into a bit of trouble with this LINQ statement (simplified slightly, the real statement has some other joins but they don't affect this particular problem so I've removed them for brevity):

var addresses = from address in Database.Addresses.All()
                           select new Address()
                               {
                                   MyNestedType = new NestedType()
                                       {
                                           Field1 = address.ADDR1
                                       }
                               };

If I execute this statement I get the error Invalid cast from 'System.String' to 'NestedType'. when I try to enumerate the results.

I'm probably overlooking the obvious but I can't see anywhere that I request such a conversion.

Both Field1 and address.ADDR1 are strings.

Any ideas what I'm doing wrong?

Edit:

I've had another look at this and in an effort to provide more information, I've created a small, complete example using SimpleRepository and an SQLite database that demonstrates the issue. Using SimpleRepository the error I get is different (Sequence contains no elements) but the result is the same. Here's the complete code:

 public class DatabaseAddress
 {
     public int Id { get; set; }
     public string Address1 { get; set; }
 }

 public class Address
 {
     public NestedType MyNestedType;
 }

 public class NestedType
 {
     public string Field1 { get; set; }
 }

 static class Program
 {
    [STAThread]
    static void Main()
    {
         var repo = new SimpleRepository("Db", SimpleRepositoryOptions.RunMigrations);
         DatabaseAddress address1 = new DatabaseAddress();
         address1.Address1 = "Test";
         repo.Add(address1);
         var all = repo.All<DatabaseAddress>();
         var addresses = from address in repo.All<DatabaseAddress>()
                         select new Address { MyNestedType = new NestedType { Field1 = address.Address1 } };
    }
 }

In this example, all contains the object added to the database, but addresses returns "Sequence contains no elements".

If I use anonymous types instead of concrete types in the select statement it works.

There's obviously a gap in my knowledge here; any help appreciated.

回答1:

You have to call ToList(), otherwise the SubSonic provider tries to do something with MyNestedType and it doesn't exist in the database.

var addresses = from address in repo.All<DatabaseAddress>().ToList()
                        select new Address { MyNestedType = new NestedType { Field1 = address.Address1 } };

Update: It also works if you call ToList afterwards, i.e.:

addresses.ToList().ForEach(address => Console.WriteLine("Address.MyNestedType.Field1 = {0}", address.MyNestedType.Field1));

I guess there is a bug in the SubSonic query provider, because it does work for anonymous types, as you mentioned.



回答2:

Please see my question and answer here.

Here's how you can test if it is the same issue:

In that sample code you posted, change Field1 in your NestedType to be named Address1. Re-run your sample. If it works, same issue and the fix I answered with in the linked question should solve it for you.



回答3:

Try this

var nestedTypes= from address in Database.Addresses.All()
                select new NestedType()
                {
                 Field1 = address.ADDR1
                };