使用一个与映射属性直接映射的[NotMapped]属性进行查询

huangapple go评论54阅读模式
英文:

Querying using a [NotMapped] property that maps directly to a mapped property

问题

以下是翻译好的部分:

我有多个连接实体,它们是用于多对多关系的桥接表。下面是一个模拟示例。属性名称是固定的(现有项目),但我在桥接表之间有一个通用接口,通过重新映射实体属性到未映射属性来实现。

是否可以设置重新映射(通过表达式、事件或其他任何方式),以便接口属性可以在 Linq 查询中用作底层属性的代理,并在服务器端解析?例如,使以下代码工作:

public List<T> GetClientFilesForRelated<T>(int RelatedId) where T : IFileRelated, class
{
    return _context.Set<T>().Where(x => x.RelatedId == RelatedId).ToList();
}
public class File
{
    public int FileId { get; set; }
}
public class Client
{
    public int ClientId { get; set; }
}
public class Company
{
    public int CompanyId { get; set; }
}
public class ClientFile : IFileRelated
{
    public int ClientFileId { get; set; }
    public int ClientId { get; set; }
    public int FileId { get; set; }
    [NotMapped]
    public int RelatedId { get => ClientId; set => ClientId = value; }
}

public class CompanyFile : IFileRelated
{
    public int CompanyFileId { get; set; }
    public int CompanyId { get; set; }
    public int FileId { get; set; }
    [NotMapped]
    public int RelatedId { get => CompanyId; set => CompanyId = value; }
}

public interface IFileRelated
{
    public int FileId { get; set; }
    public int RelatedId { get; set; }
}
英文:

I have several link entities which are bridging tables for many-many relationships. Mock example below. The property names are fixed (existing project), but I have a common interface across the bridging tables that are implemented by remapping an entity property to a notmapped property.

Is it possible to set up the remapping (through expressions or events or any other means) so that the interface property can be used in Linq queries as a proxy for the underlying property and resolved server side? E.g. make the following work:

public List&lt;T&gt; GetClientFilesForRelated&lt;T&gt;(int RelatedId) where T:IFileRelated, class
{
    return _context.Set&lt;T&gt;().Where(x=&gt;x.RelatedId==RelatedId).ToList()
}


public class File
{
    public int FileId { get; set; }
}
public class Client
{
    public int ClientId { get; set; }
}
public class Company
{
    public int CompanyId { get; set; }
}
public class ClientFile : IFileRelated
{
    public int ClientFileId { get; set; }
    public int ClientId { get; set; }
    public int FileId { get; set; }
    [NotMapped]
    public int RelatedId { get =&gt; ClientId; set =&gt; ClientId = value; }
}

public class CompanyFile : IFileRelated
{
    public int CompanyFileId { get; set; }
    public int CompanyId { get; set; }
    public int FileId { get; set; }
    [NotMapped]
    public int RelatedId { get =&gt; CompanyId; set =&gt; CompanyId = value; }
}

public interface IFileRelated
{
    public int FileId { get; set; }
    public int RelatedId { get; set; }
}

答案1

得分: 1

短回答,不行。[NotMapped] 的意思就是这样,EF 不期望也不能将其转换为 SQL。你可以这样做:

public class ClientFile : IFileRelated
{
    public int ClientFileId { get; set; }
    [Column("ClientId")]
    public int RelatedId { get; set; }
    public int FileId { get; set; }
}

public class CompanyFile : IFileRelated
{
    public int CompanyFileId { get; set; }
    [Column("CompanyId")]
    public int RelatedId { get; set; }
    public int FileId { get; set; }
}

这应该可以正常工作,但在查看这两个类时可能不太直观。

你的存储库或获取文件的方法已经有误导性:

public List<T> GetClientFilesForRelated<T>(int RelatedId) where T : IFileRelated, class

方法的名称暗示着“Client”文件,但实际上意图返回客户或公司文件。老实说,我强烈建议在涉及 EF 时避免使用泛型实现,比如泛型存储库。简单地使用以下方法:

List<ClientFile> GetClientFiles(int clientId);

List<CompanyFile> GetCompanyFiles(int companyId);

这样就很明显,这些是更简单、单一用途的方法。不需要过于担心 DRY,因为 DRY 是为了避免重复相同的代码。这些并不是相同的问题,只是相似。泛型方法是处理可以完全互换使用的类的绝佳工具。不要因为它们看起来相似就试图将每个形状的销子都塞进一个圆洞中。

英文:

Short answer, No. [NotMapped] means exactly that, EF is not expecting to, nor can translate that into SQL. What you can do would be something like this:

public class ClientFile : IFileRelated
{
    public int ClientFileId { get; set; }
    [Column(&quot;ClientId&quot;)]
    public int RelatedId { get; set; }
    public int FileId { get; set; }
}

public class CompanyFile : IFileRelated
{
    public int CompanyFileId { get; set; }
    [Column(&quot;CompanyId&quot;)]
    public int RelatedId { get; set; }
    public int FileId { get; set; }
}

Which should work fine, but won't be the most intuitive when looking at the two.

Your repository or such method to get the files is already misleading:

public List&lt;T&gt; GetClientFilesForRelated&lt;T&gt;(int RelatedId) where T:IFileRelated, class

Where the name implies "Client" files but really intends to return Client or Company files. Honestly I highly recommend avoiding Generic implementations like the Generic Repository when it comes to EF. Simply have:

List&lt;ClientFile&gt; GetClientFiles(int clientId);

and

List&lt;CompanyFile&gt; GetCompanyFiles(int companyId);

Already it should be quite evident that these are simpler, single-purpose methods. There isn't really a case for worrying about DRY as DRY is a concern to avoid duplicating identical code. These are not identical concerns, they are merely similar. Generic methods are an excellent tool for dealing with classes that can be used completely interchangeably. Avoid the temptation to squeeze every shape peg into a round hole just because they seem similar to one another.

huangapple
  • 本文由 发表于 2023年7月20日 08:16:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76725931.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定