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

瘦欲@ 提交于 2020-01-05 08:31:57

问题


This resource explains how Computed excludes a property (in an update only?).

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);
}

Doesn't Write(false) fulfill the same purpose though? What's the difference between [Computed] and [Write(false)]?

Edit:

I've just checked the resource linked in response to my question. It almost hits the nail on this! Could someone please confirm if both attributes perform the same operations, but are just worded in two different ways, as to give a better abstraction to their users?


回答1:


Both [Computed] and Write(false) will ignore the property while INSERT as well as UPDATE operations. So, both of them are same. You can use any one of it.

Documentation says below:

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

About Write:

As stated in first line in document above, Write handles "writeable" behavior. This should include both INSERT and UPDATE.

This can also be confirmed in source code 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;
}

About Computed:

Second line in document above is bit broad though.

should not be part of updates

Does that mean it can be the part of INSERT? No, it does not; it also cover both the actions. This can be observed with below code:

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);
}

With above code, you will observe that no matter which attribute you choose to decorate the property, it will neither be considered for INSERT nor for UPDATE. So basically, both the attributes are playing same role.

This can be further confirmed in Dapper.Tests.Contrib test project on github.

[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

Looking at the comment and the value assigned to the property in above code, it makes clear that Computed should also ignore the property for INSERT operation; it is expected result of the test.

Why those two ways are provided for same purpose is not known. It causes confusion.

Following are some additional references:

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.

I don't think Computed attribute has anything to do with Computed Columns as Dapper.Contrib support multiple RDBMS.



来源:https://stackoverflow.com/questions/57673107/whats-the-difference-between-computed-and-writefalse-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!