如何使用Linq to SQL在C#中将匿名类型转换为<dynamic>列表

5

我是一名新手,对C#和Linq不熟悉。

实际上,我想将匿名类型返回到列表中。这个匿名类型包含List、String和DateTime。我尝试使用下面的代码,但是它会报错。请帮忙告诉我哪里出了问题,或者建议如何实现这个目标。

//错误:

System.InvalidCastException: Specified cast is not valid..

//编辑后的 C# Linq 代码

        public List<AuditInfo> GetScanAudit(object Id, DateTime? fromTime, DateTime? toTime, string type = null,
            string user = null, Pager pager = null)
        {
            using (var ctx = new PlantDataContext())
            {
                var query = from audit in ctx.AuditLog
                            join ent in ctx.Scans on audit.RecordId equals ent.Id.ToString() into audits
                            from entaudits in audits.DefaultIfEmpty()
                            where audit.TypeFullName == "ABCD.DB.Model.Scan"
                            select new
                            {
                                audit,
                                entaudits
                            };

                if (Id != null)
                {
                    query = query.Where(x => x.audit.RecordId == Id.ToString());
                }
                if (fromTime.HasValue)
                {
                    var tmp = new DateTimeOffset(fromTime.Value.ToUniversalTime());
                    query = query.Where(x => x.audit.EventDateUTC >= tmp);
                }
                if (toTime.HasValue)
                {
                    var tmp = new DateTimeOffset(toTime.Value.ToUniversalTime());
                    query = query.Where(x => x.audit.EventDateUTC <= tmp);
                }
                if (!string.IsNullOrEmpty(type))
                {
                    var parseEvent = (EventType)Enum.Parse(typeof(EventType), type);
                    query = query.Where(x => x.audit.EventType == parseEvent);
                }
                if (!string.IsNullOrEmpty(user))
                {
                    query = query.Where(x => x.audit.UserName == user);
                }
                if (pager != null)
                {
                    var totalRecords = query.Count();
                    pager.TotalRecords = totalRecords;
                    var data = query.Select(x =>
                        new AuditInfo
                        {
                            x.audit.TypeFullName, //Here Error Occurs
                            x.audit.UserName,//Here Error Occurs
                            x.audit.EventType,//Here Error Occurs
                            x.audit.EventDateUTC,//Here Error Occurs
                            @LogDetails = x.audit.LogDetails.ToList(), //Here Error Occurs
                            x.entaudits.Name,
                            @Description = x.entaudits.Description
                        })
                        .OrderByDescending(x => x.EventDateUTC)
                        .Skip(pager.From)
                        .Take(pager.PageSize);
                    try
                    {
                        var list1 = data.ToList<AuditInfo>();
                    }
                    catch (Exception e)
                    {
                    }
                    var list = data.ToList<AuditInfo>();
                    pager.RecordCount = list.Count;
                    return list;
                }
                else
                {
                    var list = query.Select(x =>
                        new AuditInfo
                        {
                            x.audit.TypeFullName,
                            x.audit.UserName,
                            x.audit.EventType,
                            x.audit.EventDateUTC,
                            @LogDetails = x.audit.LogDetails.ToList(),
                            x.entaudits.Name,
                            @Description = x.entaudits.Description
                        })
                            .OrderByDescending(x => x.EventDateUTC)
                        .ToList<AuditInfo>();
                    return list;
                }
            }
        }

当我调试代码时,totalRecords变量显示计数为6,但在这一行var list1 = data.ToList()处显示异常信息Specified cast is not valid。


1
不太确定 sql 标签在这里是否相关。 - Caius Jard
你想在哪里使用这个方法 => GetScanAudit,为什么选择返回类型为 List<dynamic> 而不是 List<SomeClass> - er-sho
你可以使用.OrderByDescending(x => x.EventDateUTC).Cast<dynamic>().ToList() - Alessandro D'Andria
@jarlh 我真的没有看到它...我将标题解释为“Linq-to-SQL”,这是一种已经过时的数据访问技术,可能在这里被错误地应用,而不是“帮我将这个linq转换为等效的sql”..但我可能是错的。 - Caius Jard
2
返回动态类型的意义是什么?C# 是一种强类型编程语言,因此在您的情况下没有必要返回动态类型列表。如果您是 C# 的新手,应该知道强类型是好的,而应避免使用动态类型。 - Access Denied
显示剩余16条评论
2个回答

9

您需要将匿名对象转换为动态对象。

使用Linq时,可以使用Cast<dynamic> Linq方法来执行此操作:

var list = query.Select(x =>
    new
    {
        x.audit.TypeFullName,
        x.audit.UserName,
        x.audit.EventType,
        x.audit.EventDateUTC,
        @LogDetails = x.audit.LogDetails.ToList(),
        x.entaudits.Name,
        @Description = x.entaudits.Description
    })
    .OrderByDescending(x => x.EventDateUTC)
    .AsEnumerable()
    .Cast<dynamic>()
    .ToList<dynamic>(); \\ here exception occures
return list;

先生,不起作用了。 在用户代码中发生了“System.NotSupportedException”类型的异常,但未处理。 其他信息:无法将类型“匿名类型”强制转换为类型“System.Object”。LINQ to Entities仅支持将EDM基元或枚举类型进行转换。 - Sandy N
@SandyN 你可以使用.AsEnumerable()代替.Cast <dynamic> - Alessandro D'Andria
先生,仍然无法工作, “System.Data.dll”中发生了“System.InvalidCastException”的异常,但在用户代码中未被处理 附加信息:指定的转换无效。 - Sandy N
1
使用 AsEnumerable()Cast<dynamic>() 对我很有效。 - jaycer
1
非常好!谢谢。 - Ahmed Suror

4
您可以使用强类型返回值来定义您的方法,例如 List<ClassName>,而不是 List<dynamic>
public List<ClassName> GetScanAudit(object Id, DateTime? fromTime, DateTime? toTime, string type = null, string user = null, Pager pager = null)
{
   ...
}

然后您的查询将是:
var data = query.Select(x =>
                new ClassName
                {
                    TypeFullName = x.audit.TypeFullName,
                    UserName = x.audit.UserName,
                    EventType = x.audit.EventType,
                    EventDateUTC = x.audit.EventDateUTC,
                    LogDetails = x.audit.LogDetails.ToList(),
                    Name = x.entaudits.Name,
                    Description = x.entaudits.Description
                })
                .OrderByDescending(x => x.EventDateUTC)
                .Skip(pager.From)
                .Take(pager.PageSize);

var list = data.ToList<ClassName>();

你的强类型类应该像这样:
public class ClassName
{
    public string TypeFullName { get; set; }
    public string UserName { get; set; }
    public string EventType { get; set; }
    public DateTime EventDateUTC { get; set; }
    public List<LogDetail> LogDetails { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

请确保查询语句中.Select子句中每个属性的数据类型匹配。
if (pager != null)
            {
                var totalRecords = query.Count();
                pager.TotalRecords = totalRecords;
                var data = query.Select(x =>
                    new AuditInfo
                    {
                        TypeFullName = x.audit.TypeFullName,
                        UserName = x.audit.UserName,
                        EventType = x.audit.EventType,
                        EventDateUTC = x.audit.EventDateUTC,
                        LogDetails = x.audit.LogDetails.ToList(),
                        Name = x.entaudits.Name,
                        Description = x.entaudits.Description
                    })
                    .OrderByDescending(x => x.EventDateUTC)
                    .Skip(pager.From)
                    .Take(pager.PageSize);
                try
                {
                    var list1 = data.ToList<AuditInfo>();
                }
                catch (Exception e)
                {
                }
                var list = data.ToList<AuditInfo>();
                pager.RecordCount = list.Count;
                return list;
            }
            else
            {
                var list = query.Select(x =>
                    new AuditInfo
                    {
                        TypeFullName = x.audit.TypeFullName,
                        UserName = x.audit.UserName,
                        EventType = x.audit.EventType,
                        EventDateUTC = x.audit.EventDateUTC,
                        LogDetails = x.audit.LogDetails.ToList(),
                        Name = x.entaudits.Name,
                        Description = x.entaudits.Description
                    })
                        .OrderByDescending(x => x.EventDateUTC)
                    .ToList<AuditInfo>();
                return list;
            }

请确保如果 x.audit.TypeFullName 是字符串,则在 TypeFullName 类中将其定义为字符串,如果 x.audit.EventDateUTCDateTime,则在 EventDateUTC 类中将其定义为 DateTime。这意味着您必须为类属性分配适当的数据类型,以便与您的选择子句查询匹配。 - er-sho
是的,先生,我为此创建了另一个类文件。 - Sandy N
使用以下语句来定位错误所在处 => TypeFullName = x.audit.TypeFullName, UserName = x.audit.UserName, EventType = x.audit.EventType, EventDateUTC = x.audit.EventDateUTC, LogDetails = x.audit.LogDetails.ToList(), Name = x.entaudits.Name, Description = x.entaudits.Description - er-sho
只需在所有查询的选择子句中分配类似于 TypeFullName = x.audit.TypeFullName 的内容,就可以消除错误。 - er-sho
是的,那个错误已经消失了。但是这个 `ret = GetUserAudit(Id, fromTime, toTime, type, user, pager);' // 这里出现了错误。 - Sandy N
显示剩余13条评论

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