GetObjectbyKey in E.F. vs. Querying for a single entity
2010-09-06 12:39
597 查看
Even though I seem to have gotten it right when I wrote about this in my book (I just checked) in my own memory I have had a misconception about GetObjectbyKey.
I thought that GetObjectbyKey and TryGetObjectbyKey only searches the cache for entities that already have been created. But I realized this morning that if it doesn't find the entity in the cache, it will create a query and go look in the database also.
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
or use one of the methods for creating an EntityKey on the fly.
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
You can easily make this a generic method if you needed to.
Compare this to a query
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
or
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
Using GetObjectbyKey vs. a query is not just about coding because they work very differently.
When you execute a query, EF will always go to the database first and retrieve whatever it finds. As it's loading the results into the cache, if the entity already exists in the cache, it will refresh that entity based on the MergeOptions.
If MergeOption is AppendOnly (this is the default) then the newly retrieved entity will disappear into the ether.
If it is OverwriteChanges, then the values from the server will replace the current values of the entity in the cache.
If it is PreserveChanges, the values from the server will replace the original values of the entity in the cache. The current values won't be touched.
MergeOption can also be set to NoTracking. That's an interesting scenario because it will create a second instance of this object. I'm not sure how I feel about that yet. However, if you already have an entity in memory but not in the cache, GetObjectbyKey will have the same effect. It won't find the entity in the cache and will go get one and put it into the cache - result is two instances of the entity.
So depending on your needs, GetObjectbyKEy (and TryGetOBjectbyKey) is very efficient because it won't go to the database unless it has to, however it won't refresh your data from the server as a query would.
Good to know so I can make the right choice when the time comes.
I thought that GetObjectbyKey and TryGetObjectbyKey only searches the cache for entities that already have been created. But I realized this morning that if it doesn't find the entity in the cache, it will create a query and go look in the database also.
dim myEntity=context.GetObjectbyKey(myKey)
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
or use one of the methods for creating an EntityKey on the fly.
Dim cust=context.GetObjectbyKey(new EntityKey("NorthWindEntities.Customers","CustomerID",3)
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
You can easily make this a generic method if you needed to.
Compare this to a query
Dim cust= (From c in context.Customers Where c.CustomerID=3).FirstorDefault
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
or
Dim cust=context.Customers.Where(Function(c) c.CustomerID=3).FirstorDefault
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }
Using GetObjectbyKey vs. a query is not just about coding because they work very differently.
When you execute a query, EF will always go to the database first and retrieve whatever it finds. As it's loading the results into the cache, if the entity already exists in the cache, it will refresh that entity based on the MergeOptions.
If MergeOption is AppendOnly (this is the default) then the newly retrieved entity will disappear into the ether.
If it is OverwriteChanges, then the values from the server will replace the current values of the entity in the cache.
If it is PreserveChanges, the values from the server will replace the original values of the entity in the cache. The current values won't be touched.
MergeOption can also be set to NoTracking. That's an interesting scenario because it will create a second instance of this object. I'm not sure how I feel about that yet. However, if you already have an entity in memory but not in the cache, GetObjectbyKey will have the same effect. It won't find the entity in the cache and will go get one and put it into the cache - result is two instances of the entity.
So depending on your needs, GetObjectbyKEy (and TryGetOBjectbyKey) is very efficient because it won't go to the database unless it has to, however it won't refresh your data from the server as a query would.
Good to know so I can make the right choice when the time comes.
相关文章推荐
- Use GetObjectByKey() for better performance
- EJB3: Mapping of 1-to-1 relationships when primary key in the source table is also a foreign key for the target entity
- valueForKey: Vs objectForKey:
- POST请求报错:Error Domain=NSCocoaErrorDomain Code=3840 "No string key for value in object around charact
- could not get constructor for org.hibernate.persister.entity.SingleTableEntittyPersister
- Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
- Memcached ++++ exception thrown while trying to get object from cache for key
- Difference Between objectForKey and valueForKey in NSDictionary
- getsingleresult 为空报错 javax.persistence.NoResultException: No entity found for query
- WaitForMultipleObjects、WaitForSingleObject、GetExitCodeThread
- Get SQL String From Query Object In Entity Framework
- GetExitCodeThread WaitForSingleObject
- Unable to get VFS File object for filename 'file:///': Unknown scheme "sftp" in URI "{1}".
- Error:Could not get unknown property ‘apkVariantData’ for object of type com.android.build.gradle.in
- Object.key()与for...in...
- caused by org.hibernate.mappingexception repeated column in mapping for entity
- Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
- org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.Single
- Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
- GetExitCodeThread(hThrd, &exitCode);WaitForSingleObject(hThrd,INFINITE);