Some values in LINQ Query Statement aren't saved correctly to class with subsonic 3

73 Views Asked by At

I am developing a MVC 3 Application which uses Subsonic 3 for accessing the database.

My Problem is, i don't understand why the Enum "GlobalType" is not being written into the property. Everytime i check, the value is 0 instead of "One".

The "Name" property contains the "DateCreated" value.

The "DateCreated" property contains a new DateTime instance.

No other fields, as far as i'm aware of, are doing this. There is no logic inside of the ViewItemModel, it's just a class with properties.

If i add them after this method manually, everything works. Maybe someone encountered something similar with subsonic (if it even is subsonic itself, maybe i'm making a mistake)?

I have this method in the Backend:

public IEnumerable<ViewItemModel> LoadView(int registratorId)
{
    var itemModel = from item in _itemQuery
                    join header in _headerQuery on item.HeaderID equals header.ID
                    where header.RegistratorID == registratorId && !(from hidden in _headerHiddenQuery where hidden.ItemID == item.ID && hidden.Type == GlobalType.One && hidden.RegistratorID == registratorId select hidden.ID).Any()

                    orderby item.ID descending

                    select new ViewItemModel()
                    {
                        Type = GlobalType.One,

                        ID = item.ID,
                        Name = header.Name,
                        DateCreated = header.DateCreated,
                        TypeOfTransport = header.TypeOfTransport,
                        TransportType = item.TransportType,

                        Count = (from subItems in _subItemQuery where subItems.ItemID == item.ID select subItems.ID).Count(),

                        // For Status
                        IsArchived = header.IsArchived,
                        IsCanceled = header.IsCanceled,
                        Process = header.Process,
                        End = header.End,
                        IsPublished = header.IsPublished,
                        OpenFrom = header.OpenFrom,
                        OpenTill = header.OpenTill,
                        IsNextStarted = header.IsNextStarted
                    };

    return itemModel.ToList();
}

Update:

The GlobalType enum looks like this

public enum GlobalType
{
    One = 1,
    Two = 2,
    Individual = 3
}

If i add them manually, i changed the return statement for this:

var result = itemModel.ToList();

foreach (var item in result)
{
    var headerId = _itemQuery.Where(it => it.ID == item.ID).Select(it => it.HeaderID).FirstOrDefault();
    var created = _itemQuery.Where(it => it.ID == item.ID).Select(it => it.DateCreated).FirstOrDefault();
    var name = _headerQuery.Where(it => it.ID == headerId).Select(it => it.Name).FirstOrDefault();

    item.AnnouncementType = GlobalType.One;
    item.Name = name;
    item.DateCreated = created;
}

return result;
2

There are 2 best solutions below

0
KampfFussel On BEST ANSWER

Thanks to DaveParsons comment, i managed to create a workaround.

In this case, the code will have to iterate twice through the list of found elements, but won't load the entire table into memory. Since there is a bug (throwing exception) with creating an anonymous object containing multiple classes like so:

select new { item, header, subItems }

I managed to get all the data needed, by manually assigning what i need like so:

public IEnumerable<ViewItemModel> LoadView(int registratorId)
{
    var itemModel = from item in _itemQuery
                    join header in _headerQuery on item.AnnouncementHeaderID equals header.ID
                    where header.RegistratorID == registratorId && !(from hidden in _headerHiddenQuery where hidden.ItemID == item.ID && hidden.Type == GlobalType.One && hidden.RegistratorID == registratorId select hidden.ID).Any()

                    orderby item.ID descending

                    select new {
                        Type = GlobalType.One,

                        ID = item.ID,
                        Name = header.Name,
                        DateCreated = header.DateCreated,
                        TypeOfTransport = header.TypeOfTransport,
                        TransportType = item.TransportType,

                        Count = (from subItems in _subItemQuery where subItems.ItemID == item.ID select subItems.ID).Count(),

                        // For Status
                        IsArchived = header.IsArchived,
                        IsCanceled = header.IsCanceled,
                        Process = header.Process,
                        End = header.End,
                        IsPublished = header.IsPublished,
                        OpenFrom = header.OpenFrom,
                        OpenTill = header.OpenTill,
                        IsNextStarted = header.IsNextStarted
                    };

    return itemModel
            .ToList()
            .Select(it => new ViewItemModel() {

                Type = it.Type,

                ID = it.ID,
                Name = it.Name,
                DateCreated = it.DateCreated,
                TypeOfTransport = it.TypeOfTransport,
                TransportType = it.TransportType,

                Count = it.Count,

                // For Status
                IsArchived = it.IsArchived,
                IsCanceled = it.IsCanceled,
                Process = it.Process,
                End = it.End,
                IsPublished = it.IsPublished,
                OpenFrom = it.OpenFrom,
                OpenTill = it.OpenTill,
                IsNextStarted = it.IsNextStarted

            })
            .ToList();
}

Notice: The return value of the query is an anonymous object with every single necessary field declared.

After the database returned all fields with the same name as in the database (model), we then have to force execution with ".ToList()" or something similar (deferred execution?).

Since the data is now in memory, we can assign the values from the anonymous object to the original class that was intended for this purpose.

I am sure there is a more reliable way using reflection, but this is what i have come up with.

1
kari kalan On

try sample code:

       public int enum GlobalType
       {
          One = 1,
          Two = 2,
          Individual = 3
        }



   //enum value Convert to int or other data type using casting
   item.AnnouncementType = (int) GlobalType.One;

    //Suppose if condition using 
    if((GlobalType)item.AnnouncementType==GlobalType.One)
    {
       //your code
    }