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

What's the difference between [Computed] and [Write(false)] attributes?

This 资源解释了 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 来回答我的问题。它几乎击中了钉子!有人可以确认这两个属性是否执行相同的操作,但只是用两种不同的方式措辞,以便为他们的用户提供更好的抽象?

[Computed]Write(false) 都将忽略 属性 而 INSERTUPDATE 操作。所以,两者是一样的。您可以使用其中任何一种。

Documentation 表示如下:

  • [Write(true/false)] - this property is (not) writeable
  • [Computed] - this property is computed and should not be part of updates

关于Write:

如上文第一行所述,Write 处理 "writeable" 行为。这应该包括 INSERTUPDATE.

这也可以在源代码中得到证实here:

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:

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

should not be part of updates

这是否意味着它可以成为 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);
}

通过上面的代码,您会发现无论您选择哪个属性来修饰 属性,它都不会被考虑用于 INSERTUPDATE。所以基本上,这两个属性都扮演着相同的角色。

这可以在 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

I use [Computed] or [Write("False")] for that. Does that not work for your scenario?

Comment 2

Glad I could help. Every day is a school day! I'm not sure why they both exist though as I think they are functionally the same. I tend to use [Computed] just because it is marginally easier to type.

Comment 3

I understand that using Dapper.Contrib I can use the Write and Computed attributes to ignore properties during write operations. However, this will ignore the properties on both insert and update. I need a way to ignore properties on updates. My suggestion would be to add 2 attributes... perhaps named Insertable(bool) and Updateable(bool). When a false value is passed to these the framework would exclude that property for the given operation. This is a lightweight, straightforward approach to a very common problem.

我认为 Computed 属性与 Computed Columns 没有任何关系,因为 Dapper.Contrib 支持多个 RDBMS。