I have a pretty easy question regarding nHibernate but I couldn't really find an answer on google.
Let's say I have a mapped Member object that holds a 1:n foreign key to Mail objects. I would like to retrieve the current collection of mail items for a user when he enters his inbox. If I call memberInstance.Mail (of type IList<\Mail>) it brings back the mail collection but doesn't reflect the new mail that was added since the memberInstance is saved in the cache during login and doesn't make a round trip to the database. If I create a RetrieveMailForUser method, pass it a Member instance and then call code such as Session.CreateCriteria<Mail> I get the current mail for any given member and everything but it seems extraneous to have a Mail collection on the Member variable if I never use it as well as having a collection in the member var that isn't up to date. I could refresh the member every time the user checks his inbox and save it to the cache but this seems to have a lot of overhead. I feel like I'm missing some basic principal of nHibernate. Please help. Thanks!
Code that calls the member:
public static Member GetLoggedInUser()
{
var member = (Member) HttpContext.Current.Session[SESSION_NAME];
if(member != null &&
!NHibernateSessionManager.IsEntityAttachedToCurrentSession(member))
NHibernateSessionManager.AttachEntityToSession(member);
return member;
}
E
from your post I derive two contradicting requirements:
You want an object (Member) in the cache, which should not be updated according to what happens in the database. It is in the very nature of a cache NOT to automatically reload anything or trying to attempt to do so.
You want Mails in the Mails collection of the Member object to be updated whenever accessed (and therefore disregarding what was in the cache at the moment of retrieving the Member object for the first time).
If you want to stick to the first approach, you must update the Member object in the cache directly whenever a new Mail is created for that object (calling member.AddMail(mail) or something like that). I don't know whether that is feasible, since you apparently keep Member in the session, and that would require accessing Member objects of another session.
If you also want 'up to date' list of mails, I guess there is no way around either re-loading your mail list explicitly, reloading your entire object, or just loading the mails in the way you suggested it above already (RetrieveMailForUser). In that case, you can confidently remove the Mails collection in the Member object. You don't have to map collections if you don't need them.
Related
I'm working on a VSTO plugin for Outlook (C#) and find nothing about saving or embedding the state/options of my plugin with a draft message.
Is there any mean to do that ?
Ex: if my plugin makes the message to be displayed in red, I want to have my draft re-opened written in red.
Any idea ?
Use the UserProperties.Add method which creates a new user property in the UserProperties collection. Use the UserProperties property to return the UserProperties object for an Outlook item. This applies to all Outlook items except for the NoteItem.
Use the Add method to create a new UserProperty for an item and add it to the UserProperties object. The Add method allows you to specify a name and type for the new property. When you create a new property, it can also be added as a custom field to the folder that contains the item (using the same name as the property) by setting the AddToFolderFields parameter to true when calling the Add method. That field can then be used as a column in folder views.
To set for the first time a property created by the UserProperties.Add method, use the UserProperty.Value property instead of the SetProperties and SetProperty methods of the PropertyAccessor object.
If you need to keep the data for the folder or Outlook account in general (not per item) you may consider the StorageItem instead. That is a message object in MAPI that is always saved as a hidden item in the parent folder and stores private data for Outlook solutions.
The Outlook object model does not provide any collection object for StorageItem objects. However, you can use Folder.GetTable to obtain a Table with all the hidden items in a Folder, when you specify the TableContents parameter as olHiddenItems. If keeping your data private is of a high concern, you should encrypt the data before storing it.
As Eugene advised, you can use MailItem.UserProperties collection to set/read your custom properties.
A couple points to consider - since named properties are a finite resource, you can have at most 32k of them per mailbox. Once you go over, the mailbox is pretty much dead. So use as few unique properties as possible, and definitely do not use anything dynamic, such as the message subject in the property name.
If you set a user property on an outgoing message, Outlook might force it to go out in the TNEF format. To prevent that from happening, set the property value using MailItem.PropertyAccessor.SetProperty. You can use the same DASL property name that your user property uses, but the point is to avoid using the UserPropeties collection. You can see the DASL property name in OutlookSpy (I am its author) - select a message with your user property set, click IMessage button, select your property, see the DASL edit box.
I'm trying to come up with a generic model for associating some contextual data with an object in C#. I have built a caching system that can be described as follows...
Background Story -> The cache is a singleton implementation that provides "readonly" access to frequently requested information that is part of a custom CMS implementation that I use for various asp.net applications. I update the data via a desktop application I have written and the next time the web server loads the cache my changes are reflected to visitors.
My cache adheres to the following...
Every object has a unique id
Any object can be associated with any other object by an id mapping defined in an association table
No matter how many associations to a particular object exist, only one instance of that object is loaded into the cache.
For example...Object A might associate to a collection of Object C's. Similarly Object B might also associate to a collection of Object C's. If one were to request an Object C with id 23 from an instance of Object A and then request an Object C with id 23 from Object B, they would get a handle to the same instance of Object C.
I now have some data to add into the picture but the data does not belong to Object A by itself and it does not belong to Object C by itself. The data is information specific to the association of Object A with Object C.
My First Idea: Keep the additional data separate from Object C since it doesn't actually belong to Object C by itself. Maintain this information within Object A and allow it to be looked up in a Dictionary. I don't like the way the data has to be accessed in this approach. I would rather have direct access to the additional data via Object C or a derived class for binding purposes and ease of use.
My Second Idea: Create a derived class from Object C (call it Object D) that includes the additional contextual data and provides properties for easy access. This addresses the binding and gives me the ease of use that I was looking for. My problem with this approach is that now my Object A is referring to a collection of Object D's and I am required to break my above model by duplicating the entirety of Object A's data just so that I can append some extra association information.
What I would really like is to continue having only one instance of Object C for a given id and append some contextual data and properties that can be easily accessed in the appropriate context. Can this be done? I'm also open for any other suggestions here! I want my solution to be generic and sound so I can forget about it and not have that constant itch to go back and find a better solution.
The Objec C instances should hold there own data. Of course you can store the "path" in it via what the object was retrieved from the cache (via Object A or Object B), but storing this kind of information in the object, modifies the object, so if it were to be retrieve via another "path", the information will be overrwritten.
A solution could be to clone object C every time it is retrieved from the cache and store your "path" in it, or store your extra data if it came via Object A?
This way, all objects inside your cache are shared as requested, but stand alone once outside the cache.
I ended up going with my second idea. Object D became a special type of object that has it's own properties/members/methods but also has a property that returns an Object C. Object D must implement a specific interface to be identified by my caching algorithm. I updated my caching system to ensure that if the Object C returned by the property has already been loaded, that one is returned instead of loading up an additional copy from the db.
I have a list of class object that I created as a variable in my deafault.aspx.cs page
List<BoldGauge> boldGauges = new List<BoldGauge>();
I create my object in nessacary function and then add the newly created object to the list so I can retrieve it later as needed.
When I attempt loop through the object later the boldGagues count = 0. I assume I need to either add the List to a session variable or session state.
Does anyone know the best approach for this? There could be numerous different types of controls in multiple lists, so if someone could please recommend an approach that is least expensive, and efficient I would appreciate it.
To persist the list across postbacks, you'll need to store the list somewhere.
You can store it in the Session, but a more applicable place might be the ViewState.
ViewState.Add("GaugesList", boldGauges);
then get it back later
List<BoldGauges> boldGauges = ViewState["GaugesList"];
Note that this is scoped to the page, so if you need the list across pages, use the Session.
foreach(var boldGaug in boldGauges)
{
//do something..
}
I have a few fields on a list that was created using a schema. The schema and list seem to have gotten out of sync, so when I try to change attributes for a field on the schema, those changes are not reflected on the list, unless they are additions (ie, new fields).
I have a few Sealed fields that I need to unseal. But when I attempt to set Sealed=false, either using SharePoint Manager, or using a utility I wrote, I get the error:
"Operation is not valid due to the current state of the object." I can't seem to find any more usable information about the error.
On my utility, this happens on the line:
field.Sealed = false;
I haven't even gotten to the point of trying to update the field before an exception is thrown. field.SchemaXml looks fine too. I don't see anything wrong with it.
This is happening on multiple fields in this list.
Anyone know what to do?
What is the error and what is the field that is failing?
According to MSDN, you cannot change out of the box or external data fields:
InvalidOperationException: An attempt is made to assign a value to a field type that is built into SharePoint. The true/false value of such fields must remain at its factory setting.
NotSupportedException: An attempt is made to assign false when the SharePoint field is an external data column.
Update (to highlight information that might be hidden in the comments):
Call SPBuiltInFieldId.Contains to avoid (or detect) InvalidOperationException. The Sealed property cannot be set if SPBuiltInFieldId.Contains returns true.
Following up on Rich's answer, if you need to modify a column that is in the SPBuiltInFieldId collection, you can set the GUID of the column to new GUID() during runtime then make any changes to the column you need. Be careful, there is a reason that Microsoft attempts to lock you out of editing these columns. I needed to fix the list relationship for the Resources (Facilities) column in my group calendar and this allowed me to do so.
I'm working on a .NET phone application where I have a list of items in memory that are displayed to the user. When the user clicks on an item in the user interface, they'll be brought to the "details" view for that item in a second view. I'm currently using an identity property in my class to reference unique items in the list, but I'm wondering if there is a better way.
I'm using System.Windows.Navigationto set up UriMappings like so:
<nav:UriMapping Uri="/Items/{itemId}"
MappedUri="/Views/Items.xaml?itemId={itemID}" />
I then use the NavigationService to navigate like so:
NavigationService.Navigate(new Uri("/Items/" + item.id.ToString(),
UriKind.Relative));
All of this works great, but I don't know that I like needing to include an identity column for my Item class just so that can have a unique string identifer to pass in to the MappedUri query string. My user interface control that shows the list gives me the underlying Item object in the SelectionChanged event, so I'm wondering if there's a way to "match" that Item object with a unique string value to its corresponding reference in the list. If I could provide a simple object reference to the navigation service, this would be easy, but I'm not sure how to do it with a string value. Is this what GetHashCode() is for, and if so, how do I use it correctly?
No, GetHashCode is not intended to uniquely identify objects.
The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.
It is designed for storing objects in buckets (for example in a dictionary) so that they can be quickly retrieved. The hash codes for two equal objects must be equal, but the hash codes for two different objects do not have to be different.
I think adding an Id field is a fine solution. If you don't like adding a new field just to give an object an identity you can try to find some combination of the existing fields that is guarateed to uniquely identify your object and concetenate their string representations with a suitable separator. Be careful that the separator cannot occur in any of the fields.
There's a GUID which you can use that maps to each string in the list, by calling a NewGuid method of the Guid class, one can generate a Guid and use that as a string type via ToStringmethod and use it for hashing strings.
You definitely want to provide the item's ID. Bear in mind that your application may be tombstoned, so the object may not even be in memory any more when you try to navigate to that page. You need to be able to restore the application to the page with no information other than the URL and whatever's been serialized to temporary or permanent storage (typically in OnNavigateFrom).
Using GetHashCode() for this not only doesn't guarantee uniqueness, but it's highly unlikely to work in terms of the newly restored application, too. Life gets a lot harder when you're trying to display the details of something where you haven't really got an ID... but it doesn't sound like you're really in that position.
As it looks like you've got an ID, use it as an ID. Why would you want to use anything else? If you don't have an ID but can easily add one, do so. You want a way of uniquely identifying an object... that's exactly what an ID is for.