[Computed] 和 [Write(false)] 属性有什么区别?

6

这篇资源解释了在更新时Computed如何排除一个属性。

Specifie the property should be excluded from update.

[Table("Invoice")]
public class InvoiceContrib
{
    [Key]
    public int InvoiceID { get; set; }
    public string Code { get; set; }
    public InvoiceKind Kind { get; set; }
    [Write(false)]
    [Computed]
    public string FakeProperty { get; set; }
}
using (var connection = My.ConnectionFactory())
{
    connection.Open();
    var invoices = connection.GetAll<InvoiceContrib>().ToList();
    // The FakeProperty is skipped
    invoices.ForEach(x => x.FakeProperty += "z");
    var isSuccess = connection.Update(invoices);
}

Write(false)是否实现了同样的目的?[Computed][Write(false)]之间有什么区别?

编辑:

我刚刚查看了linked资源以回答我的问题。它几乎完全解决了这个问题!请问是否可以确认两个属性执行相同的操作,只是用两种不同的方式表达,以便更好地抽象化它们的用户?

1个回答

13

无论是[Computed]还是Write(false), 都会在进行INSERTUPDATE操作时忽略该属性。因此,它们都是相同的,您可以使用任意一个。

文档中如下所述:

  • [Write(true/false)] - 此属性可(不可)写入
  • [Computed] - 此属性已计算,不应成为更新的一部分

关于Write

如上面文档中第一行所述,Write处理“可写”行为。这应包括INSERTUPDATE

这也可以在源代码此处中确认:

var properties = type.GetProperties().Where(IsWriteable).ToArray();
...
...
...
private static bool IsWriteable(PropertyInfo pi)
{
    var attributes = pi.GetCustomAttributes(typeof(WriteAttribute), false).AsList();
    if (attributes.Count != 1) return true;

    var writeAttribute = (WriteAttribute)attributes[0];
    return writeAttribute.Write;
}

关于Computed

虽然上面文档中的第二行有点宽泛。

不应该成为更新的一部分

这是否意味着它可以是INSERT的一部分? 不,它不是; 它也涵盖了两种操作。 可以通过以下代码观察到:

CREATE TABLE TestTable
(
    [ID]            [INT] IDENTITY (1,1) NOT NULL CONSTRAINT TestTable_P_KEY PRIMARY KEY,
    [Name]          [VARCHAR] (100) NOT NULL,
    [ComputedCol]   [VARCHAR] (100) NOT NULL DEFAULT '',
    [NonWriteCol]   [VARCHAR] (100) NOT NULL DEFAULT ''
)

[Table("TestTable")]
public class MyTable
{
    [Key]
    public int ID { get; set; }

    public string Name { get; set; }

    [Computed]
    public string ComputedCol { get; set; }

    [Write(false)]
    public string NonWriteCol { get; set; }
}

int id;
using(SqlConnection conn = new SqlConnection(@"connection string"))
{
    MyTable myTable = new MyTable();
    myTable.Name = "Name";
    myTable.ComputedCol = "computed";
    myTable.NonWriteCol = "writable";

    conn.Insert<MyTable>(myTable);

    id = myTable.ID;
}

using(SqlConnection conn = new SqlConnection(@"connection string"))
{
    MyTable myTable = conn.Get<MyTable>(id);
    myTable.Name = "Name_1";
    myTable.ComputedCol = "computed_1";
    myTable.NonWriteCol = "writable_1";

    conn.Update<MyTable>(myTable);
}

使用以上代码,您会发现无论您选择哪个属性来装饰该属性,它既不会被考虑用于INSERT也不会被考虑用于UPDATE。因此,两个属性基本上扮演相同的角色。
这可以在github上的Dapper.Tests.Contrib测试项目中进一步确认。
[Table("Automobiles")]
public class Car
{
    public int Id { get; set; }
    public string Name { get; set; }
    [Computed]
    public string Computed { get; set; }
}
...
...
...
//insert with computed attribute that should be ignored
connection.Insert(new Car { Name = "Volvo", Computed = "this property should be ignored" });

Source: 1 and 2

在上面的代码中,通过观察注释和属性分配的值可以清楚地看出,Computed还应该忽略INSERT操作中的属性;这是测试的预期结果。
为同一目的提供这两种方式的原因尚不清楚,这会引起困惑。
以下是一些额外参考: Comment 1 我使用[Computed][Write("False")]。对于你的场景没有用吗? Comment 2 很高兴我能帮忙。每天都是学校日!不过我不确定为什么它们都存在,因为我认为它们在功能上是相同的。我倾向于使用[Computed],因为打字稍微容易一些。 Comment 3 我知道使用Dapper.Contrib可以使用WriteComputed属性在写入操作期间忽略属性。但是,这将忽略插入和更新的属性。我需要一种方法来在更新时忽略属性。我的建议是添加2个属性...可能命名为Insertable(bool)Updateable(bool)。当传递false值时,框架将排除给定操作的该属性。这是解决一个非常常见问题的轻量级、直接的方法。
我认为Computed属性与计算列无关,因为Dapper.Contrib支持多个RDBMS。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接