How to determine if entity field was excluded while fetching data from database?

Posts   
 
    
Posts: 34
Joined: 05-Mar-2008
# Posted on: 10-Mar-2011 12:28:58   

Hi,

I have a question about excluded included fields list. Is there any chance to get know which fields for particular entity were excluded for fetching in OnCanLoadEntity event handler?

I need it because we have something like checksum policy. Each entity has got a CheckSum field. Just before saving entity, our checksum engine calculates hash value for every field. These hashed values are stored as a string in CheckSum field. When entity is fetched we can check if all checksums for fields are correct which means that there was no any unauthorized manipulation directly in database. And it works fine. But now we want to use exclude fields list to speed up some controls. If I do this and I fetch such an entity I have a problem while checking the CheckSum. If field was excluded it's value is i.e. string.empty. The calculated checksum for string.empty is not the same as a calculated value for original field value. Then application throws CheckSumException.

What I am looking for is a property on EntityField which tells me that field was excluded while fetching was done. Thanks this I could just ignore this field and do not throw checksum exception.

Is there any property like described above or can I add it somehow by myself?

thanks! Dawid

P.S. I am using Adapter. DLLs: ORMSupportClassesNET20 ver. 2.6.10.225 (product ver. 2.6.10.0225)

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 10-Mar-2011 19:09:32   

Hi Dawid,

There is nothing in the entity you can use for that. The Exclude list is used in the fetch process and the entity is fetch-agnostic or stateless, that means the entity doesn't have information about the fetch process. What you can do is:

  1. Define a CheckSum property on the CommonEntityBase
  2. Override the SaveEntity routine in the DataAccessAdapter class. In there you will check the exlude list and fill your checksum custom property based on that.
  3. Now in OnCanLoadEntity you can check your CheckSum entity.

Hope that makes sense to you.

David Elizondo | LLBLGen Support Team
Posts: 34
Joined: 05-Mar-2008
# Posted on: 11-Mar-2011 11:04:45   

daelmo wrote:

Hi Dawid,

There is nothing in the entity you can use for that. The Exclude list is used in the fetch process and the entity is fetch-agnostic or stateless, that means the entity doesn't have information about the fetch process. What you can do is:

  1. Define a CheckSum property on the CommonEntityBase
  2. Override the SaveEntity routine in the DataAccessAdapter class. In there you will check the exlude list and fill your checksum custom property based on that.
  3. Now in OnCanLoadEntity you can check your CheckSum entity.

Hope that makes sense to you.

Thanks for reply.

  1. I already have it. I also have an interface and all entities which contains CheckSum field in database implements this interface. I did it via custom template and plugin.

  2. I think this is not enough. One type of entity may be used with or within exclude fields - based on context. If I override SaveEntity routine than can be two different scenarios. One when entity has got excluded fields and other when this is "full" entity. Checksums for both would be different.

  3. Based on what I wrote above I am not able to determine if previous save was on excluded fields entity or full/regular entity. And I still don't know if current fetch contains excluded fields or not.

Maybe if I override FetchEntity I would be able to set some custom property "ExcludedFieldList" and then in CommonEntityBase would be able to use this property and skip some fields during checksum authorization? But I am not sure which method could be overridden for this? OnCanLoadEntity is called to fast. I need somthing called just after Fetching is done. Is there any good base method for that?

I can also do it by myself, but not sure if producing topology ordered list is fast enough. I want to use exclude fields to speed up application and this may bring opposite effect. What do you think?

 public class DataAccessAdapterExtended : DataAccessAdapter
    {
        public override bool FetchEntity(IEntity2 entityToFetch, .IPrefetchPath2 prefetchPath, .Context contextToUse, ExcludeIncludeFieldsList excludedIncludedFields)
        {
            bool returnValue = base.FetchEntity(entityToFetch, prefetchPath, contextToUse, excludedIncludedFields);

            ObjectGraphUtils ogu = new ObjectGraphUtils();
            List<IEntity2> targetList = ogu.ProduceTopologyOrderedList(entityToFetch);

            foreach (CommonEntityBase entity in targetList)
            {
                entity.CheckIfCheckSumValid(excludedIncludedFields);
            }
            
            return returnValue;
        }
    
    }

Of course I would like to have similar functionality for FetchEntityCollection. So I need to iterate through collection items and produce topology tree for every entity in collection.. Would it be a big hit for performance?

Thanks for any advice!

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 11-Mar-2011 12:14:38   

IMHO, since this is validation, you can use a Vaildator for this. And thus you can perform the check in ValidateEntityAfterLoad.

Posts: 34
Joined: 05-Mar-2008
# Posted on: 11-Mar-2011 12:22:33   

Walaa wrote:

IMHO, since this is validation, you can use a Vaildator for this. And thus you can perform the check in ValidateEntityAfterLoad.

I have tried to use it but it is called just inside the base.FetchEntity so I am not able to pass any information (excludeFieldList) to entity to use it during validation.

Any other ideas? Can you say something about the performance risk in the solution I have described in previous post?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 11-Mar-2011 12:41:35   

As you have to do the checksum validation for each entity, I see no extra performance penalty in your approach.

Posts: 34
Joined: 05-Mar-2008
# Posted on: 14-Mar-2011 15:49:41   

Walaa wrote:

As you have to do the checksum validation for each entity, I see no extra performance penalty in your approach.

Hi again!

I have made some performance tests for following method:

public override void FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket, int maxNumberOfItemsToReturn, ISortExpression sortClauses, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList excludedIncludedFields, int pageNumber, int pageSize)
        {

            base.FetchEntityCollection(collectionToFill, filterBucket, maxNumberOfItemsToReturn, sortClauses, prefetchPath, excludedIncludedFields, pageNumber, pageSize);

            ObjectGraphUtils ogu = new ObjectGraphUtils();

            foreach (IEntity2 fetchedEntity in collectionToFill)
            {
                List<IEntity2> targetList = ogu.ProduceTopologyOrderedList(fetchedEntity);

                foreach (CommonEntityBase entity in targetList)
                {
                    entity.ValidateCheckSum(excludedIncludedFields);
                }
            }
        }

I have moved my validation logic (which is quite simple) from OnCanLoadEntity to ValidateCheckSum - to support checksums for excluded fetches. And what I have noticed is:

  1. When there is no prefetch path for fetch routine, producing topology lists and doing a validation for every entity works pretty good. Cost time for this operation is about 20% of overall method. So for fetching data from db I need 5 secund and for doing validation 1 second.

  2. When the prefetch path is more complex (4 entities inside the graph), time cost for these operations increases drastically even up to 90% for more complex graph.

This approach is not acceptable. Is there really not other way to push some information about exclude fields to the entity/entity collection before it will be created and use it during OnCanLoad or OnvalidateBeforeLoad? Maybe I can do some workaround, modify entity template or even something else.

This is one missing piece and I need it to finish the whole checksum/exclude fields task for our application. If I won't find it, we have to throw it away... frowning

Please help!

Thanks, Dawid

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 15-Mar-2011 06:09:14   

[quotenick="dprzespolewski"]

Walaa wrote:

public override void FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket, int maxNumberOfItemsToReturn, ISortExpression sortClauses, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList excludedIncludedFields, int pageNumber, int pageSize)
        {

            base.FetchEntityCollection(collectionToFill, filterBucket, maxNumberOfItemsToReturn, sortClauses, prefetchPath, excludedIncludedFields, pageNumber, pageSize);

            ObjectGraphUtils ogu = new ObjectGraphUtils();

            foreach (IEntity2 fetchedEntity in collectionToFill)
            {
                List<IEntity2> targetList = ogu.ProduceTopologyOrderedList(fetchedEntity);

                foreach (CommonEntityBase entity in targetList)
                {
                    entity.ValidateCheckSum(excludedIncludedFields);
                }
            }
        }

This approach is not acceptable. Is there really not other way to push some information about exclude fields to the entity/entity collection before it will be created and use it during OnCanLoad or OnvalidateBeforeLoad? Maybe I can do some workaround, modify entity template or even something else. Dawid

What I see so far is that you are building a topology ordered list for every entity in the collection. Isn't enough to make just one topological list and check them all? ObjectGraphUtils ogu = new ObjectGraphUtils();

List<IEntity2> targetList = ogu.ProduceTopologyOrderedList(fetchedEntity);

                foreach (CommonEntityBase entity in targetList)
                {
                    entity.ValidateCheckSum(excludedIncludedFields);
                }

Another option is to fill some property in CommonEntityBase where you put the excludedIncludedFields, you do this in that fetch routine. That way you can check that property on OnCanLoadEntity. This is not so clean solution but it could help you indeed.

David Elizondo | LLBLGen Support Team
Posts: 34
Joined: 05-Mar-2008
# Posted on: 15-Mar-2011 09:39:17   

[quotenick="daelmo"]

dprzespolewski wrote:

Walaa wrote:

public override void FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket, int maxNumberOfItemsToReturn, ISortExpression sortClauses, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList excludedIncludedFields, int pageNumber, int pageSize)
        {

            base.FetchEntityCollection(collectionToFill, filterBucket, maxNumberOfItemsToReturn, sortClauses, prefetchPath, excludedIncludedFields, pageNumber, pageSize);

            ObjectGraphUtils ogu = new ObjectGraphUtils();

            foreach (IEntity2 fetchedEntity in collectionToFill)
            {
                List<IEntity2> targetList = ogu.ProduceTopologyOrderedList(fetchedEntity);

                foreach (CommonEntityBase entity in targetList)
                {
                    entity.ValidateCheckSum(excludedIncludedFields);
                }
            }
        }

This approach is not acceptable. Is there really not other way to push some information about exclude fields to the entity/entity collection before it will be created and use it during OnCanLoad or OnvalidateBeforeLoad? Maybe I can do some workaround, modify entity template or even something else. Dawid

What I see so far is that you are building a topology ordered list for every entity in the collection. Isn't enough to make just one topological list and check them all? ObjectGraphUtils ogu = new ObjectGraphUtils();

List<IEntity2> targetList = ogu.ProduceTopologyOrderedList(fetchedEntity);

                foreach (CommonEntityBase entity in targetList)
                {
                    entity.ValidateCheckSum(excludedIncludedFields);
                }

Thanks for the reply. The idea to build topology ordered list is good for FetchEntityMethod. Mine example where I build these lists is for FetchEntityCollection method. I have to do this for every fetched entity in the list. I think this is OK. Correct me if I am wrong. But still this is not efficient.

Your another suggestion is to pass extra information to entity before fetch and us them during validation in OnCanLoadEntity. It would be great but I don't know how to do this. I will try to explain this problem on FetchEntityCollection. I am passing EntityCollection<EntityA> as a parameter to FetchEntityCollectionMethod. The prefetch path defines that EntityB, C and D should be attached for EntityA during fetch.

So what I have got now is an empty collection of type EntityA. I expecting 10 entities of this type and and every of this entity should contain entityB,C,D as a sub entity. I am in the overriden FetchEntityCollection method just be fore calling base FetchEntityCollection. My question is how can pass information about excluded fields to non existing entities?

If I could have access to FetchEntityCollection of DataAccessAdapterBase I could set a custom property of CommonEntityBase for every entity during a fetch routine. Then I would be able to use my custom property in OnCanLoadEntity without these time consuming operation like building topology ordered list and others.. I think our license covers source code, so is it possible to modify a little bit code of base FetchEntityCollection? If not, do you have any other ideas?

Thanks, Dawid

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 15-Mar-2011 13:34:22   

It's possible I think, as the persistence info of fields to fetch is null for excluded fields, right before the query is constructed. I'll look into the sourcecode where you can use this info. This is more appropriate than checking the excluded fields list, because fk fields are always fetched, regardless of whether they're excluded or not, so you'd get wrong results in your checksum routine.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 15-Mar-2011 13:49:14   

In a partial class of DataAccessAdapter, override ReadRowIntoFields(). This method does the entity row reading. It gets a couple of parameters. One is the values array which is the row from the datareader. It also gets a List<Pair<int, int>>, fieldIndexToOrdinal. It contains for each field which wasn't actually read from the database a column ordinal of -1, which is Value2 of the pair objects in that dictionary. The value1 is the field index of the field in the fields object passed in as rowDestination.

So first you call the base implementation. This reads the values into the fields. Then you traverse the list. For all pairs, where the Value2 is -1, you set the field corresponding with index Value1 to a custom object, which is an instance of a class you create, e.g. ExcludedValue, doesn't matter.

Then, to avoid cast issues, you add in a partial class of CustomEntityBase, an override of the method PostProcessValueToGet. There, you check whether the value to return is an instance of your special class, e.g. ExcludedValue. If so, return null, otherwise return the value you got passed in.

In your checksum calculation routine, you should check the entityfield2's CurrentValue property. If that property is an instance of your special class, you can skip the field, otherwise read the value using entity.GetValue(index).

This approach works always, also when you fetch a single entity, so IMHO the best approach to solve your problem, and it takes little effort simple_smile Of course, if you code reading the CurrentValue property directly, it won't work if it runs into the special class instance and it expects null. It's easy to solve that though: simply use entity.GetValue() instead.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 05-Mar-2008
# Posted on: 15-Mar-2011 15:35:44   

Otis wrote:

In a partial class of DataAccessAdapter, override ReadRowIntoFields(). This method does the entity row reading. It gets a couple of parameters. One is the values array which is the row from the datareader. It also gets a List<Pair<int, int>>, fieldIndexToOrdinal. It contains for each field which wasn't actually read from the database a column ordinal of -1, which is Value2 of the pair objects in that dictionary. The value1 is the field index of the field in the fields object passed in as rowDestination.

So first you call the base implementation. This reads the values into the fields. Then you traverse the list. For all pairs, where the Value2 is -1, you set the field corresponding with index Value1 to a custom object, which is an instance of a class you create, e.g. ExcludedValue, doesn't matter.

Then, to avoid cast issues, you add in a partial class of CustomEntityBase, an override of the method PostProcessValueToGet. There, you check whether the value to return is an instance of your special class, e.g. ExcludedValue. If so, return null, otherwise return the value you got passed in.

In your checksum calculation routine, you should check the entityfield2's CurrentValue property. If that property is an instance of your special class, you can skip the field, otherwise read the value using entity.GetValue(index).

This approach works always, also when you fetch a single entity, so IMHO the best approach to solve your problem, and it takes little effort simple_smile Of course, if you code reading the CurrentValue property directly, it won't work if it runs into the special class instance and it expects null. It's easy to solve that though: simply use entity.GetValue() instead.

Thanks Frans! This exactly what I was looking for! Although I have got one more question. I don't understand the part with overriden "ReadRowIntoFields". What I should do when during traversing the pairs list, I noticed that Value2 is -1. See code below:

 public partial class DataAccessAdapter
    {
        protected override void ReadRowIntoFields(object[] values, IEntityFields2 rowDestination, List<ValuePair<int, int>> fieldIndexToOrdinal, IFieldPersistenceInfo[] fieldsPersistenceInfo)
        {
            base.ReadRowIntoFields(values, rowDestination, fieldIndexToOrdinal, fieldsPersistenceInfo);

            for (int i = 0; i < fieldIndexToOrdinal.Count; i++)
            {
                if (fieldIndexToOrdinal[i].Value2 == -1)
                {
                    //this is probably wrong
                    fieldIndexToOrdinal[i] = new SD.LLBLGen.Pro.ORMSupportClasses.ValuePair<int, int>(fieldIndexToOrdinal[i].Value1, -666);
                } 
            }
        }
    }

Probably you meant to override a value for "values" parameter under the index fieldIndexToOrdinal[i].Value1. But I think this is wrong.. Lets say that there is an entity with 50 fields. One field is excluded. So:

values.count => 49 fieldIndexToOrdinal.count => 50 fieldsPersistenceInfo.coutn => 49

So this excluded field is missing in 'values' and fieldsPersistenceInfo. Should I add new objects to values and fieldsPersistenceInfo? And then assign my fancy object to them? Or am I missing something..

Thanks in advance!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 15-Mar-2011 15:56:05   

The values & persistenceinfo objects are for the base method. The objects you should focus on is rowDestination

you should do

rowDestination[fieldIndexToOrdinal[i].Value1].CurrentValue = <yourmagicobject>;

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 05-Mar-2008
# Posted on: 15-Mar-2011 16:21:49   

Otis wrote:

The values & persistenceinfo objects are for the base method. The objects you should focus on is rowDestination

you should do

rowDestination[fieldIndexToOrdinal[i].Value1].CurrentValue = <yourmagicobject>;

Thanks,

I must say that I didn't check this parameter. Sorry about that simple_smile

I have followed your instruction but now I receive this exception while doing this:


rowDestination[fieldIndexToOrdinal[i].Value1].CurrentValue = new object;

[SD.LLBLGen.Pro.ORMSupportClasses.ORMValueTypeMismatchException] = {"The value System.Object is of type 'System.Object' while the field is of type 'System.String'"}

My excluded field is a type string. The exception is not thrown only when I assign a string to it. Problem is that there can by different types that string disappointed Any solution for that?

Thanks again!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 15-Mar-2011 17:03:25   

Oh my bad, I should have told you that. Use the method entityfield.ForcedCurrentValueWrite(value)

this will write the value no matter what and won't do any type checks. You therefore have to make sure the value is post-processed properly with the override in CommonEntityBase, as I described above simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 05-Mar-2008
# Posted on: 16-Mar-2011 12:45:47   

Otis wrote:

Oh my bad, I should have told you that. Use the method entityfield.ForcedCurrentValueWrite(value)

this will write the value no matter what and won't do any type checks. You therefore have to make sure the value is post-processed properly with the override in CommonEntityBase, as I described above simple_smile

Indeed ForcedCurrentValueWrite solves the problem. Now everything works good. Except one thing simple_smile I forgot to mention that our application is distributed. And we are using WCF for communication client - server. Client asks about bunch of entity with some excluded fields. Server fetches them. Some tricks that you showed me are done on the server side. Checksums validation works. Then entity collection needs to be serialized and send to client end. And now there is a problem in XMLHelper class - method


public static string PropertyValueToString(bool datesInXmlDataType, bool mlInCDataBlocks, object propertyValue, Type propertyType, 
                                out bool valueInCDataBlock)

It throws InvalidCastException.


System.InvalidCastException was unhandled by user code
  Message=Specified cast is not valid.
  Source=SD.LLBLGen.Pro.ORMSupportClasses.NET20
  StackTrace:
       at SD.LLBLGen.Pro.ORMSupportClasses.XmlHelper.PropertyValueToString(Boolean datesInXmlDataType, Boolean mlInCDataBlocks, Object propertyValue, Type propertyType, Boolean& valueInCDataBlock)
       at SD.LLBLGen.Pro.ORMSupportClasses.XmlHelper.WriteValueAsStringToXml(Type propertyType, Object value, Boolean verboseXml, Boolean writeTypeInfoIfNull, XmlWriter writer, Boolean datesInXmlDataType, Boolean mlInCDataBlocks)
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityField2.WriteXml(XmlWriter writer, XmlFormatAspect aspects)
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityFields2.WriteXml(XmlWriter writer, XmlFormatAspect aspects)
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2.Entity2Xml(String rootNodeName, XmlWriter writer, Dictionary`2 processedObjectIDs, XmlFormatAspect aspects, Boolean isRootElement)
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase2`1.EntityCollection2Xml(String rootNodeName, XmlWriter writer, Dictionary`2 processedObjectIDs, XmlFormatAspect aspects, Boolean emitFactory, Boolean isRootElement)
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase2`1.WriteXml(XmlWriter writer, XmlFormatAspect aspects, String rootNodeName)
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase2`1.WriteXml(XmlWriter writer, XmlFormatAspect aspects)
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase2`1.WriteXml(XmlWriter writer)
       at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteIXmlSerializable(XmlWriterDelegator xmlWriter, Object obj, XmlSerializableWriter xmlSerializableWriter)
       at System.Runtime.Serialization.XmlDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
       at System.Runtime.Serialization.NetDataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContract contract, Hashtable surrogateDataContracts)
       at System.Runtime.Serialization.NetDataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
       at System.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
       at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
       at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
       at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest)
       at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
       at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
       at System.ServiceModel.Channels.BinaryMessageEncoderFactory.BinaryMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
       at AbacaSystems.AbacaNET.WCF.GZipMessageEncoder.GZipMessageEncoderFactory.GZipMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) in D:\fp\Abaca\AbacaNET\src\WCF\AbacaSystems.AbacaNET.WCF.GZipMessageEncoder\GZipMessageEncoderFactory.cs:line 198
       at System.ServiceModel.Channels.FramingDuplexSessionChannel.EncodeMessage(Message message)
       at System.ServiceModel.Channels.FramingDuplexSessionChannel.OnSend(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.OutputChannel.Send(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServerReliableChannelBinder`1.DuplexServerReliableChannelBinder`1.OnSend(TDuplexChannel channel, Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ReliableChannelBinder`1.Send(Message message, TimeSpan timeout, MaskingMode maskingMode)
  InnerException: 


My magic object assigned when Value2 == -1 looks like this:


 [Serializable]
    public class MyExcludeObject
    {
        
    }

We are using NetDataSerializer for WCF and some external component GZipMessageEncoder to zip the message send via WCF. When I turned off GZipMessageEncoder there is no exception but sending entity collection doesn't work properly. If excluded field is type of string on the client side, field value contains "AbacaSystems.General.Classes.MyExcludeObject" If excluded field is type of DataTime, there is no exception thrown but I receive an empty collection after fetch on the client side.

If it would help I could try to download your WCF sample and try to repeat en error by modifying your example. But I think the problem is in the XML serialization. Property type is i.e. DateTime and in fact real object is different. Thats why there is a cast excaption in your code. Is there any chance to workaround this ?

Thanks, Dawid

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 18-Mar-2011 05:07:59   

Trying to reproduce your behavior...

(Edit) Do you need the checksum on the client side? What is you define your magic class like this?:

[Serializable]
public class MyExcludeObject
{
    public override string ToString()
    {
        return string.Empty;
    }
}
David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 18-Mar-2011 08:44:44   

I indeed think that David's solution might be the trick. Otherwise you've to dig into the xml serialization code, and as it's tight, it's not that extensible.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 34
Joined: 05-Mar-2008
# Posted on: 18-Mar-2011 10:12:51   

I decided to extend EntityBase2 by adding a custom property which contains a list of excluded fields indexes. Then in DataAccessAdapterBase in methods for fetching entity and entity collection I am filling in this property just before base CanLoadEntity is called. So now I can use my custom property during checksum validation in my code.

In other words I modify your code by adding extra information to entity. It is maybe not elegant but it works and doesn't seem to impact for other things i.e. like serialization.

We are not gonna to upgrade to llbl gen ver.3 so once I build ORMSupport.dll it can be used by our code without any further modification, hopefully simple_smile

Thank you guys for the whole effort you put into this thread! Without your help it would be very hard to find a proper solution simple_smile

Cheers, Dawid