Databases Reference
In-Depth Information
return authorizationAttribute == null
| | authorizationAttribute.
IsAuthorized
(user, action);
}
In any performance-critical method, such as
IsAuthorized
, it is important to minimize
the amount of reflection-based code executed repeatedly. This code relies on the
TypeDescriptor
API to locate the
AuthorizationAttribute
and, to minimize the perfor-
mance impact, caches the search results in the static
authorizationAttributes
dictionary.
When the
AuthorizationAttribute
for a given entity type has been located, next time it
is retrieved from the dictionary, resulting in a much faster execution.
The
IsAuthorized
method can be executed by several different threads simultaneously,
especially in a web application, and has to be thread-safe. To implement thread-safe caching,
this code uses the
ConcurrentDictionary
type from the
System.Collections.Concurrent
namespace, which offers a specialized method
GetOrAdd
for safely retrieving an existing
value from the dictionary or adding it if it does not exist. As its second parameter, this
method takes a
function
that is executed if the dictionary does not contain a value for the
given key; the value it returns is stored in the dictionary and returned to the caller of the
GetOrAdd
method. It is this anonymous function (this example uses the shorter
lambda
syntax to define it) where the code calls the
TypeDescriptor.GetAttributes
method to find
the
AuthorizationAttribute
.
Extending ObjectContext to Enforce Read Permission
The
SaveChanges
method of the
ObjectContext
allows you to enforce only the Insert,
Update, and Delete permissions. Because this method does not have to be called by code
retrieving entities from the database, you cannot enforce the Read permission here. It is
actually quite challenging to authorize the Read actions properly because there are so
many different ways of reading the entity information. First, there is the straightforward
access through the
ObjectSet
properties, which can be illustrated with code like this:
using (var context = new NorthwindEntities())
{
var supplierInformation = context.Suppliers;
}
You can implement Read authorization for the Suppliers object set by changing imple -
mentation of its property. Here is the default implementation of the
Suppliers
property
in the
NorthwindEntities
class generated by the built-in Entity Framework code genera-
tor, which was modified to call the
Authorize
method of the
UnleashedObjectContext
base class:
public ObjectSet<Supplier> Suppliers
{
get
{
Authorize(typeof(Supplier), Actions.Read);
if (_Suppliers == null)