我之前就写过一篇《实现UniqueAttribute唯一性约束》,虽然实现了通过调用IsValid方法可以进行唯一性验证,但有一个缺点,那就是耦合度过高,原因是里面的DB上下文对象是直接写在里面的,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public
override
Boolean IsValid(Object value)
{
bool
validResult =
false
;
//TEMSContext 是我项目中的DB上下文类,这里是直接指定的,与TEMSContext 紧耦合,若需要实体与访问分离就会有问题!
using
(TEMSContext context =
new
TEMSContext())
{
string
sqlCmd=
string
.Format(
"select count(1) from [{0}] where [{1}]=@p0"
,tableName,filedName);
context.Database.Connection.Open();
var
cmd=context.Database.Connection.CreateCommand();
cmd.CommandText = sqlCmd;
var
p0 = cmd.CreateParameter();
p0.ParameterName =
"@p0"
;
p0.Value = value;
cmd.Parameters.Add(p0);
int
result=Convert.ToInt32(cmd.ExecuteScalar());
validResult=(result<=0);
}
return
validResult;
}
|
现在为了解决这个问题,我目前采用的是通过属性注入DB上下文类型,然后再采取反射动态创建实例,这样就降低了依赖,完整代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
using
System;
using
System.ComponentModel.DataAnnotations;
using
System.Data.Entity;
namespace
Zwj.TEMS.Common
{
/// <summary>
/// 唯一性标识
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple =
false
, Inherited =
true
)]
public
class
UniqueAttribute : ValidationAttribute
{
protected
string
tableName;
protected
string
filedName;
<strong>
public
Type ContextType {
private
get
;
set
; }
public
UniqueAttribute(
string
tableName,
string
filedName)
{
this
.tableName = tableName;
this
.filedName = filedName;
}
public
override
Boolean IsValid(Object value)
{
//如果是系统调用,就不会传入ContextType类型,所以此处就直接返回通过
if
(
this
.ContextType ==
null
)
{
return
true
;
}
bool
validResult =
false
;
using
(DbContext context = ContextType.Assembly.CreateInstance(ContextType.FullName)
as
DbContext)
{
string
sqlCmd =
string
.Format(
"select count(1) from [{0}] where [{1}]=@p0"
, tableName, filedName);
context.Database.Connection.Open();
var
cmd = context.Database.Connection.CreateCommand();
cmd.CommandText = sqlCmd;
var
p0 = cmd.CreateParameter();
p0.ParameterName =
"@p0"
;
p0.Value = value;
cmd.Parameters.Add(p0);
int
result = Convert.ToInt32(cmd.ExecuteScalar());
validResult = (result <= 0);
context.Database.Connection.Close();
}
return
validResult;
}
}
}
</strong>
|
这样虽然降低了对实际DB上下文的依赖,但新问题又出来了,就是如果通过手动来验证该特性(如下代码)就没有问题,但如是想让EF框架在RUD时能自动验证,则会出现问题,因为没有传入ContextType,所以也就无法进行验证,我想这也是微软之所以没有实现UniqueAttribute唯一性约束的原因吧,不知道哪位高手能指点一下,非常感谢!
以下是手动来验证该特性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
void
ValidateEntity(
object
entity)
{
var
t = entity.GetType();
var
properties = t.GetProperties();
foreach
(
var
p
in
properties)
{
UniqueAttribute[] attrs;
if
(p.TryGetAttribute<UniqueAttribute>(
out
attrs))
{
attrs[0].ContextType=
typeof
(TEMSContext);
bool
result = attrs[0].IsValid(p.GetValue(entity,
null
));
Assert.IsTrue(result,
"验证不唯一,存在重复值!"
);
}
}
}
|
本文转自 梦在旅途 博客园博客,原文链接: http://www.cnblogs.com/zuowj/p/4397943.html ,如需转载请自行联系原作者