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

Sup*_*Bob 3 c# attributes dapper dapper-contrib

资源解释了如何Computed排除属性(仅在更新中?)。

指定应从更新中排除该属性。

[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);
}
Run Code Online (Sandbox Code Playgroud)

Write(false)达到同样的目的吗?[Computed]和 和有[Write(false)]什么区别?

编辑:

我刚刚检查了为回答我的问题而链接的资源。它几乎一针见血!有人可以确认这两个属性是否执行相同的操作,但只是以两种不同的方式表达,以便为用户提供更好的抽象?

Ami*_*shi 7

双方[Computed]Write(false)会忽略的财产,同时INSERT还有UPDATE操作。所以,两者都是一样的。您可以使用其中任何一种。

文档如下:

  • [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;
}
Run Code Online (Sandbox Code Playgroud)

关于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 ''
)
Run Code Online (Sandbox Code Playgroud)
[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; }
}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,您会发现无论您选择哪个属性来装饰该属性,都不会考虑 forINSERT或 for 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" });
Run Code Online (Sandbox Code Playgroud)

资料来源:12

看上面代码中的注释和分配给属性的值,很明显Computed应该忽略该属性进行INSERT操作;这是测试的预期结果。

为什么为同一目的提供这两种方式尚不清楚。它会引起混乱。

以下是一些额外的参考:

评论 1

我使用[Computed][Write("False")]为此。这对您的场景不起作用吗?

评论 2

很高兴我能帮助你。每一天都是上学日!我不确定为什么它们都存在,因为我认为它们在功能上是相同的。我倾向于使用[Computed]只是因为它更容易打字。

评论 3

我知道使用 Dapper.Contrib 我可以使用WriteComputed属性在写操作期间忽略属性。但是,这将忽略插入和更新的属性。我需要一种方法来忽略更新的属性。我的建议是添加 2 个属性......也许命名Insertable(bool)Updateable(bool). 当一个false值传递给这些时,框架将排除给定操作的该属性。这是一种解决非常常见问题的轻量级、直接的方法。

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